sql - 使用 WHILE LOOP 在 SQL Server 2008 中迭代 SELECT 语句

标签 sql sql-server-2008 while-loop iteration

我有一个数据库,其中提供了员工 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/

相关文章:

asp.net - 如何在 SQL Server 表中创建图像列并使用 VB 在 ASP.NET 中检索它

java - 接受所有输入后如何跳出 while 循环?

c++ - 循环和条件的 boolean 变量

mysql - 寻找 SQL 查询的替代方案

sql-server-2008 - 在 DB 或 SSRS 中计算列的最佳方法

SQL Server - 测试存储过程的结果

javascript - 循环函数和数组: javascript

SQL - min() 获得最低值,max() 获得最高值,如果我想要第二个(或第五个或第 n 个)最低值怎么办?

php - 多个数据库连接

SQL Server Management Studio - 如何在不删除表的情况下更改字段类型