在分组时使用XML PATH来操作行数据

时间:2014-06-23 05:12:00

标签: sql sql-server xml winforms pivot

在sql查询中,我试图做两件事。

我有一张像这样的表Attendance

EID |  PID  |      In_Time     |     Out_Time      | Shift 
__________________________________________________________
100 |  S001 | 2014-05-01 07:10 |  2014-05-01 19:20 |   D
100 |  S001 | 2014-05-04 07:00 |  2014-05-04 19:00 |   D
100 |  S001 | 2014-05-04 19:00 |  2014-05-05 07:00 |   N

EID -EmployeeID

PID -PointID(位置)

D - Day Shift

N - 夜班

当我按除Shift之外的所有字段进行分组时,(仅对DatePartIn_Time字段进行分组时,我想得到此内容

中间步骤

EID |  DAY | Shift |
___________________
100 |  01  |  D    |
100 |  04  |  D/N  |

最后,我希望PIVOT获得以下结果

预期最终结果

EmployeeID | 01 | 02 | 03 | 04  |
__________________________________
100        |  D | _  | _  | D/N |

我在这个目的中使用以下查询,但结果略有不同。

SELECT EID AS EmployeeID, [1],[2],[3],[4] 
FROM (

SELECT 
  EID, datepart(dd,in_time) as [DAY],
  STUFF((
    SELECT '/ ' + Shift  
    FROM Attendance  
    WHERE ([in_time] = Results.[in_time] ) 
    FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')
  ,1,2,'') AS Shifts 
FROM Attendance Results 
WHERE EID = '100' AND PID ='C002' 
GROUP BY EID , in_time
) AS SourceTable 

 PIVOT
 (
 MAX (Shifts ) 
 FOR [DAY] IN ( [1],[2],[3],[4])
 ) AS PivotTable

这是查询的结果

   EmployeeID | 01 | 02 | 03 | 04  |
   ________________________________
   100        |  D | _  | _  | N/N |

我的查询出了问题,请你帮忙解决这个问题吗?我在此查询中遗漏了哪些内容?你知道更好的方法吗?

编辑:我刚刚意识到只要出勤表包含与单个员工和单个点(PID)相关的记录,上述代码就能正常运行。

如果上表列出了在不同地点(PID)工作的几名员工(EID)的详细信息,则输出错误。所以我看到代码不一致,但我在sql中的知识似乎不足以在没有帮助的情况下解决这个问题:(

1 个答案:

答案 0 :(得分:0)

以下答案可能会对您有所帮助。 SQL看起来很冗长,但逻辑很简单,只需将D和N数据分组并最终加入。也许你可以从中工作。

DECLARE @Lu_Dt table
(id int identity(1,1),Dt Date)
INSERT INTO @Lu_Dt VALUES('2014-05-01'),
('2014-05-02'),('2014-05-03'),
('2014-05-04'),('2014-05-05')

DECLARE @tab table
(EID int,PID varchar(15),In_Time datetime,Out_Time datetime,[Shift] Char(1))
INSERT INTO @tab Values
(100,'S001','2014-05-01 07:10','2014-05-01 19:20','D'),
(100,'S001','2014-05-04 07:00','2014-05-04 19:00','D'),
(100,'S001','2014-05-04 19:00','2014-05-05 07:00','N')

SELECT * FROM @tab

enter image description here

DECLARE @refTab table
(id int identity(1,1),EID int, Dt Date,[shift] varchar(3))

INSERT INTO @refTab

SELECT      Lu.EID,Lu.Dt,coalesce(LU1.[Flag],LU2.[Flag]) [shift]
FROM        (SELECT *,100 EID FROM @Lu_Dt) Lu
LEFT JOIN   (SELECT D.EID,D.In_Time,'D/N' [Flag]
            FROM    (SELECT EID,CAST(In_Time AS DATE) In_Time FROM @tab Where Shift = 'D') D
            JOIN    (SELECT EID,CAST(In_Time AS DATE) In_Time FROM @tab Where Shift = 'N') N 
            ON      D.In_Time = N.In_Time AND D.EID = N.EID) LU1 ON Lu.Dt = LU1.In_Time
LEFT JOIN   (SELECT CAST(In_Time AS DATE) In_Time,'D' [Flag] FROM @tab Where Shift = 'D') LU2 ON Lu.Dt = LU2.In_Time
LEFT JOIN   (SELECT CAST(In_Time AS DATE) In_Time,'N' [Flag] FROM @tab Where Shift = 'N') LU3 ON Lu.Dt = LU3.In_Time

SELECT * FROM @refTab

enter image description here

SELECT  *
FROM    (SELECT EID,Dt,[shift] from @refTab) As src 
PIVOT
(MAX([shift]) for Dt in 
    (   [2014-05-01],
        [2014-05-02],
        [2014-05-03],
        [2014-05-04],
        [2014-05-05])) AS PivotTable;

<强>结果

enter image description here

因为有很多硬编码,所以不能这样使用。希望这有帮助。