【问题标题】:Using XML PATH to manipulate row data when grouping分组时使用 XML PATH 操作行数据
【发布时间】:2014-06-23 05:12:00
【问题描述】:

在 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 -员工ID

PID -PointID(位置)

D - 白班

N - 夜班

当我按除 Shift 以外的所有字段进行分组时,(当仅对 In_Time 字段中的 DatePart 进行分组时)我想得到这个

中间步骤

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 方面的知识似乎不足以在没有帮助的情况下解决这个问题:(

【问题讨论】:

  • Out_Time = 2014-05-05 07:00 怎么样。它没有显示在您想要的结果中。您是否只将时间视为员工的工作日?
  • @Jithin Shaji,是的,班次属于 In_Time 的那一天。所以我不想得到Out_Time。 Out_Time 将仅用于对班次进行分类
  • 我删除了一些不需要的东西以使其更简单

标签: sql sql-server xml winforms pivot


【解决方案1】:

以下答案可能对您有所帮助。 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

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

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;

结果

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

【讨论】:

  • 非常感谢。它有帮助。如果您不介意,您能否解释一下您的代码的第二部分(以 INSERT INTO @refTab... 开头)会很有帮助。
  • 我将结果保存到了一个临时表@refTab 中,这样编写 PIVOT 语句就不会那么复杂了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-17
  • 2010-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多