我有一个数据库,其中提供了员工 ID、职位、有效日期和部门。如果一名员工从事多项工作,他们将获得额外的一行数据。我的目标是将每个员工对应的行压缩为一行。基本上我需要一个从数据库中提取的查询,如下所示:
EmpID Job EffDate Dept
001 QB 01-01-2001 OFF
001 LB 01-01-2010 DEF
001 K 01-01-2005 SPEC
002 HC 01-01-2007 STAFF
003 P 01-01-2001 SPEC
003 CB 01-01-2002 DEF
像这样输出:
EmpID Job1 EffDate1 Dept1 Job2 EffDate2 Dept2 Job3 EffDate3 Dept3
001 QB 01-01-2001 OFF K 01-01-2005 SPEC LB 01-01-2010 DEF
002 HC 01-01-2007 STAFF
003 P 01-01-2001 SPEC CB 01-01-2002 DEF
到目前为止我已经做到了:
SELECT
EmpNo
, Job
, EffDate
, Dept
, ROW_NUMBER() OVER (PARTITION BY EmpNo ORDER BY EffDate) AS RowNum
INTO #temp1
FROM JobHist
ORDER BY EffDate DESC
SELECT
JobHist.EmpNo
, JobHist.Job AS Job1
, JobHist.EjhJobDesc AS JobDesc1
, JobHist.EffDate AS EffDate1
, JobHist.Dept AS Dept1
, temp2.Job AS Job2
, temp2.EffDate AS EffDate2
, temp2.Dept AS Dept2
FROM #temp1 AS JobHist LEFT JOIN #temp1 AS temp2 ON JobHist.EmpNo = temp2.EmpNo AND temp2.RowNum = 2
WHERE JobHist.RowNum = 1
效果很好。问题是我需要创建很多列,并且我不想将所有代码编写 20 次。所以我想使用 WHILE 命令进行迭代。这是我在第二个 SELECT 语句中尝试的内容:
DECLARE @Flag INT
DECLARE @FlagPlus INT
SET @Flag = 1
SET @FlagPlus = (@Flag + 1)
WHILE(@Flag < 20)
BEGIN
SELECT
<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="9aeefff7eadadcf6fbfdb4dff7ead4f5" rel="noreferrer noopener nofollow">[email protected]</a>
, <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1266777f6252547e73753c587d70" rel="noreferrer noopener nofollow">[email protected]</a> AS Job@Flag
, <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8efaebe3fecec8e2efe9a0cbe4e6c4e1eccaebfded" rel="noreferrer noopener nofollow">[email protected]</a> AS JobDesc@Flag
, <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7a0e1f170a3a3c161b1d543f1c1c3e1b0e1f" rel="noreferrer noopener nofollow">[email protected]</a> AS EffDate@Flag
, <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f286979f82b2b49e9395dcb6978286" rel="noreferrer noopener nofollow">[email protected]</a> AS Dept@Flag
FROM #temp1 AS temp@Flag
LEFT JOIN #temp@Flag AS temp@FlagPlus
ON <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6713020a1727210b060049220a172908" rel="noreferrer noopener nofollow">[email protected]</a> = <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="87f3e2eaf7c7c1ebe6e0d7ebf2f4a9c2eaf7c9e8" rel="noreferrer noopener nofollow">[email protected]</a> AND <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e490818994a4a2888583b4889197cab68b93aa9189" rel="noreferrer noopener nofollow">[email protected]</a> = @FlagPlus
WHERE JobHist.RowNum = 1
SET @Flag = (@Flag + 1)
SET @FlagPlus = (@FlagPlus + 1)
END
我知道这可能行不通,因为 SQL 无法理解我尝试调用每个表和字段的命名约定。有没有一种方法可以使用强制转换或连接命令来自动化该过程,以便它只增加我要求的数字?
最佳答案
首先,让我澄清一下,这并不是问题的直接答案。然而,由于代码块很大,它也不适合评论,而且我觉得它确实为问题增加了值(value)。所以就这样了...
拥有动态数量的列很少是一个好的解决方案。如果可以选择使用 XML,我会选择不同的解决方案:
SELECT
e.EmpNo,
(SELECT
h.Job,
h.EffDate,
h.Dept
FROM JobHist h
WHERE e.EmpNo = h.EmpNo
ORDER BY EffDate DESC
FOR XML PATH('job'), ROOT('jobs'), TYPE
) Jobs
FROM (SELECT DISTINCT EmpNo FROM JobHist) e
关于sql - 使用 WHILE LOOP 在 SQL Server 2008 中迭代 SELECT 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12290731/