在SQL中将行更改为列

时间:2018-10-19 05:34:52

标签: sql sql-server tsql pivot

我有以下数据:

CREATE TABLE TimeLog (
    [User] NVARCHAR(6),
    [Event] NVARCHAR(3),
    [Time] DATETIME
);

INSERT INTO TimeLog VALUES
    (N'Jibran',N'IN','2015-04-15 00:31:00'),
    (N'Jibran',N'IN','2015-04-16 20:10:00'),
    (N'Jibran',N'IN','2015-04-21 14:59:00'),
    (N'Jibran',N'OUT','2015-04-22 01:01:00'),
    (N'Jibran',N'IN','2015-04-22 10:46:00'),
    (N'Jibran',N'OUT','2015-04-23 00:58:00'),
    (N'Jibran',N'IN','2015-04-23 14:50:00'),
    (N'Jibran',N'OUT','2015-04-24 01:37:00')

我希望每个事件(对于每个IN / OUT)都有一个新列,其中用户和时间为行。

2 个答案:

答案 0 :(得分:0)

将聚合函数与大小写一起使用

select user, max(case when Event='IN' then DATETIME end) as IN_time,
max(case when Event='OUT' then DATETIME end) as Out_time from t
group by user

答案 1 :(得分:0)

我假设您正在为每个用户连续发生INOUT事件,请正确按日期排序(与示例数据中的情况完全不同)。

您可以使用ROW_NUMBERINOUT事件成对分组,如下所示:

SELECT ROW_NUMBER() OVER (PARTITION BY [User] ORDER BY [Time])  + ROW_NUMBER() OVER (PARTITION BY [User] ORDER BY [Time]) % 2 AS [PairID]
      ,*
FROM [dbo].[TimeLog];

enter image description here

然后PIVOT获得以下结果:

SELECT [User]
      ,[IN]
      ,[OUT] 
FROM
(
    SELECT ROW_NUMBER() OVER (PARTITION BY [User] ORDER BY [Time]) + ROW_NUMBER() OVER (PARTITION BY [User] ORDER BY [Time]) % 2 AS [PairID]
          ,*
    FROM [dbo].[TimeLog]
) DS
PIVOT
(
    MAX([Time]) FOR [Event] IN ([IN], [OUT])
) PVT
ORDER BY [PairID];

enter image description here

请注意,我已将您的IN事件之一更改为OUT,以便清理数据。如果在您的实际示例中这是不正确的,我想您仍然可以使用上面的逻辑。例如,对于您的示例数据,最大的IN事件是get,而没有OUT事件:

enter image description here

您可以使用代码,将MAX更改为MIN或使用您的业务逻辑对其进行扩展。