将2行合并为1行(开始和结束时间)

时间:2019-12-16 09:10:07

标签: sql sql-server merge gaps-and-islands

我不确定该如何措辞,但我在单独的行中有StartEnd次,我想将它们合并为一行。在此示例数据中,它基本上是跟踪/记录项目时间:

Project  Type    Time
A        Start   1:00
A        End     1:10
B        Start   2:00
B        End     2:10
B        Start   2:30
B        End     2:45
C        End     3:00
D        Start   3:10
D        End     3:20

我正在寻找的东西是这样的:

Project  Start    End
A        1:00     1:10
B        2:00     2:10
B        2:30     2:45
C        NULL     1:10
D        3:10     3:20

奇怪的两个部分是:

  • 我可能对同一项目有多个开始/结束时间对(例如 (如上面的项目B),可能会在同一天背靠背或分开
  • 我可能缺少一些开始或结尾 时间。

有人能指出我正确的方向吗?我在Stackoverflow上找不到任何具有相同要求的东西。

2 个答案:

答案 0 :(得分:2)

我们可以在ROW_NUMBER的帮助下尝试在此处使用透视逻辑:

WITH cte AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY Project, Type ORDER BY Time) rn
    FROM yourTable
)

SELECT
    Project,
    MAX(CASE WHEN Type = 'Start' THEN Time END) AS Start,
    MAX(CASE WHEN Type = 'End'   THEN Time END) AS [End]
FROM cte
GROUP BY
    Project,
    rn
ORDER BY
    Project,
    rn;

screen capture of demo below

Demo

答案 1 :(得分:2)

这是种隔and问题。

我将使用lag()和一个窗口sum()来解决这个问题。每当连续记录类型不为'Start'后跟'End'时,都会创建一个新组。

select 
    project, 
    min(case when type = 'Start' then time end) Start,
    max(case when type = 'End' then time end) [End]
from (
    select
        t.*,
        sum(case when type = 'End' and lag_type = 'Start' then 0 else 1 end) 
            over(partition by project order by time) grp
    from (
        select
            t.*,
            lag(type) over(partition by project order by time) lag_type
        from mytable t
    ) t
) t
group by project, grp
order by project, grp

Demo on DB Fiddle

Project | Start | End 
:------ | :---- | :---
A       | 1:00  | 1:10
B       | 2:00  | 2:10
B       | 2:30  | 2:45
C       | null  | 3:00
D       | 3:10  | 3:20