单个查询,根据初始列返回多行作为列

时间:2012-08-13 08:55:46

标签: sql sql-server c#-4.0

我有一张表,员工历史如下

ID | Current_Dept | Dept_Start_Date | Name
1 | Sales | 2012-01-01 | John Smith
1 | Marketing | 2010-01-01 | John Smith
1 | Intern | 2008-01-01 | John Smith
2 | IT | 2012-01-01 | Sue Jones
2 | Sales | 2011-01-01 | Sue Jones
2 | eBusiness | 2010-10-01 | Sue Jones
3 | Warehouse | 2012-01-01 | Bobby Ray
3 | Sales | 2009-01-01 | Bobby Ray

我想要的是一个查询,为每个曾在Sales中工作的人提供:

ID | DeptBefore | DeptAfter | CurrentDept
1  | Marketing  |           | Sales
2  | ebusiness  | IT        | IT
3  |            | Warehouse | Warehouse

目前我看到没有更简单的方法可以做到这一点,然后以递归方式查询每一行的表格。

我很想创建一个每天填充一次的“临时”表并运行查询。

我正在使用SQL Server和C#(ASP.NET),因为这些提供了其他更简单的解决方案。

我希望一切都有道理。

谢谢,

2 个答案:

答案 0 :(得分:1)

从您的数据出现,您希望销售部门之前和之后的部门immediately。例如;你没有表明John Smith是一名实习生。

注意:如果有人在两个不同场合为销售工作,您可能需要考虑所需的结果。

WITH
  sequenced AS
(
  SELECT
    *,
    ROW_NUMBER() OVER (PARTITION BY id ORDER BY dept_start_date DESC) AS sequence_id
  FROM
    yourTable
)
SELECT
  salesRecord.id,
  prevRecord.current_dept     AS DeptBefore,
  nextRecord.current_dept     AS DeptAfter,
  lastRecord.current_dept     AS DeptCurrent
FROM
  sequenced     AS salesRecord
LEFT JOIN
  sequenced     AS prevRecord
    ON  prevRecord.id          = salesRecord.id
    AND prevRecord.sequence_id = salesRecord.sequence_id - 1
LEFT JOIN
  sequenced     AS nextRecord
    ON  nextRecord.id          = salesRecord.id
    AND nextRecord.sequence_id = salesRecord.sequence_id + 1
LEFT JOIN
  sequenced     AS lastRecord
    ON  lastRecord.id          = salesRecord.id
    AND lastRecord.sequence_id = 1
WHERE
  salesRecord.CurrentDept = 'Sales'

通过按降序排序项目,当前记录始终为sequence_id = 1

答案 1 :(得分:1)

使用CTE可以帮助您。

DECLARE @Temp TABLE
(
    ID INT,
    current_dept NVARCHAR(100),
    Dept_Start_Date DATETIME,
    Name NVARCHAR(100)
)

INSERT INTO @Temp
(ID, current_dept, Dept_Start_Date, Name)
VALUES
(1, 'Sales', '2012-01-01', 'John Smith'), 
(1, 'Marketing', '2010-01-01', 'John Smith'), 
(1, 'Intern', '2008-01-01', 'John Smith'),
(2, 'IT', '2012-01-01', 'Sue Jones'), 
(2, 'Sales', '2011-01-01', 'Sue Jones'), 
(2, 'eBusiness', '2010-01-01', 'Sue Jones'),
(3, 'Warehouse', '2012-01-01', 'Bobby Ray'),
(3, 'Sales', '2009-01-01', 'Bobby Ray')

DECLARE @current_dept NVARCHAR(100) = 'Sales'
;WITH CurrentDeptCTE AS 
(
    SELECT ID, current_dept, Dept_Start_Date, Name, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Dept_Start_Date DESC) AS SEQUENCE
    FROM @Temp
)
SELECT SalesDept.ID, DeptBefore.current_dept AS 'DeptBefore', DeptAfter.current_dept     AS 'DeptAfter', CurrentDept.current_dept AS 'CurrentDept'
FROM
(
    SELECT ID, SEQUENCE
    FROM CurrentDeptCTE
    WHERE current_dept = @current_dept
) SalesDept
LEFT JOIN CurrentDeptCTE AS DeptBefore ON SalesDept.ID = DeptBefore.ID AND            SalesDept.SEQUENCE = DeptBefore.SEQUENCE - 1
LEFT JOIN CurrentDeptCTE AS DeptAfter ON SalesDept.ID = DeptAfter.ID AND SalesDept.SEQUENCE = DeptAfter.SEQUENCE + 1
LEFT JOIN 
(
    SELECT ID, current_dept
    FROM CurrentDeptCTE 
    WHERE SEQUENCE = 1
) CurrentDept ON SalesDept.ID = CurrentDept.ID