如何在 SQL 中实现链
How to achieve chains in SQL
我有一个出勤 sheet 显示如下:
我正在尝试将人们的出席情况(编码为 ABC、DEF 等)链接在一起。
我希望最终结果如下所示:显示每个 segment/chain 出席的开始和结束日期。如果 A 人从 2021-01-01 到 2021-01-4 参加,那么它应该显示为一排,因为它是一个连续的链。我不确定该做什么或从哪里开始。这是保存考勤数据的一种奇怪方式。
更多信息:我不知道这是否重要,但我最多有 20 列,因为我们的出席人数上限为 20 人。所以这取决于 Col20.
备案。最好以文本形式提供示例数据。
这是一个有点扭曲的经典 Gaps-and-Islands。
在这里,我们通过一些 JSON 动态反透视您的数据(实际上没有使用动态 SQL)。
示例或dbFiddle
;with cte as (
Select AttendanceDate
,B.*
,Grp = datediff(day,0,AttendanceDate) - dense_rank() over (partition by value order by AttendanceDate)
From YourTable A
Cross Apply (
Select [Key]
,Value
From OpenJson((Select A.* For JSON Path,Without_Array_Wrapper ))
Where [Key] not in ('AttendanceDate')
) B
)
Select [Value]
,[Start] = min(AttendanceDate)
,[End] = max(AttendanceDate)
From cte
Group By Value,Grp
Returns
Value Start End
ABC 2021-01-01 2021-01-04
DEF 2021-01-01 2021-01-03
GH 2021-01-02 2021-01-05
DEF 2021-01-07 2021-01-08
xx 2021-01-08 2021-01-10
zz 2021-01-08 2021-01-08
我有一个出勤 sheet 显示如下:
我正在尝试将人们的出席情况(编码为 ABC、DEF 等)链接在一起。 我希望最终结果如下所示:显示每个 segment/chain 出席的开始和结束日期。如果 A 人从 2021-01-01 到 2021-01-4 参加,那么它应该显示为一排,因为它是一个连续的链。我不确定该做什么或从哪里开始。这是保存考勤数据的一种奇怪方式。
更多信息:我不知道这是否重要,但我最多有 20 列,因为我们的出席人数上限为 20 人。所以这取决于 Col20.
备案。最好以文本形式提供示例数据。
这是一个有点扭曲的经典 Gaps-and-Islands。
在这里,我们通过一些 JSON 动态反透视您的数据(实际上没有使用动态 SQL)。
示例或dbFiddle
;with cte as (
Select AttendanceDate
,B.*
,Grp = datediff(day,0,AttendanceDate) - dense_rank() over (partition by value order by AttendanceDate)
From YourTable A
Cross Apply (
Select [Key]
,Value
From OpenJson((Select A.* For JSON Path,Without_Array_Wrapper ))
Where [Key] not in ('AttendanceDate')
) B
)
Select [Value]
,[Start] = min(AttendanceDate)
,[End] = max(AttendanceDate)
From cte
Group By Value,Grp
Returns
Value Start End
ABC 2021-01-01 2021-01-04
DEF 2021-01-01 2021-01-03
GH 2021-01-02 2021-01-05
DEF 2021-01-07 2021-01-08
xx 2021-01-08 2021-01-10
zz 2021-01-08 2021-01-08