我有一组按日期排序的行,如下所示:
2017-01-01
2017-01-01
2017-01-02
2017-01-03
2017-01-04
2017-01-17
2017-01-18
2017-01-18
2017-01-18
2017-01-19
2017-01-19
2017-01-26
2017-01-27
2017-01-27
Run Code Online (Sandbox Code Playgroud)
DDL & DML 为那些愿意提供帮助的人:
CREATE TABLE foo ( DateCol date );
INSERT INTO foo ( DateCol )
VALUES
( '2017-01-01' ),
( '2017-01-01' ),
( '2017-01-02' ),
( '2017-01-03' ),
( '2017-01-04' ),
( '2017-01-17' ),
( '2017-01-18' ),
( '2017-01-18' ),
( '2017-01-18' ),
( '2017-01-19' ),
( '2017-01-19' ),
( '2017-01-26' ),
( '2017-01-27' ),
( '2017-01-27' )
);
Run Code Online (Sandbox Code Playgroud)
我正在尝试对行进行分组并添加一个额外的列来标记该组。标准是,如果它们之间的时间间隔小于 3 天,则任意两行应在一组中,如下所示:
2017-01-01 A
2017-01-01 A
2017-01-02 A
2017-01-03 A
2017-01-04 A
2017-01-17 B
2017-01-18 B
2017-01-18 B
2017-01-18 B
2017-01-19 B
2017-01-19 B
2017-01-26 C
2017-01-27 C
2017-01-27 C
Run Code Online (Sandbox Code Playgroud)
如何做到这一点?
我建议分解问题,首先给出行和有序 id 并链接到以下日期,然后找到差异,然后找到差异何时大于 3 天的案例,并将行设置为 1 或 0。然后你应该能够对该列进行累积和以设置一个组。
CREATE TABLE #groupedDates(
[date] datetime,
[group] nvarchar(max))
INSERT INTO #groupedDates ([date], [group])
SELECT '2017-01-01', ''
UNION ALL
SELECT '2017-01-01', ''
UNION ALL
SELECT '2017-01-02', ''
UNION ALL
SELECT '2017-01-03', ''
UNION ALL
SELECT '2017-01-04', ''
UNION ALL
SELECT '2017-01-17', ''
UNION ALL
SELECT '2017-01-18', ''
UNION ALL
SELECT '2017-01-18', ''
UNION ALL
SELECT '2017-01-18', ''
UNION ALL
SELECT '2017-01-19', ''
UNION ALL
SELECT '2017-01-19', ''
UNION ALL
SELECT '2017-01-26', ''
UNION ALL
SELECT '2017-01-27', ''
UNION ALL
SELECT '2017-01-27', ''
SELECT [id],[startDate],[endDate], CASE WHEN [dif] <=3 THEN 0 ELSE 1 END [changeGroup]
INTO #tempA
FROM (
SELECT [start].[s] AS [id], [start].[date] AS [startDate], ISNULL([end].[date],[start].[date]) AS [endDate],
ISNULL(DATEDIFF(dd,[start].[date],[end].[date]),0) AS [dif]
FROM (
SELECT [date] , ROW_NUMBER() OVER (ORDER BY [date]) AS [s]
FROM #groupedDates) AS [start]
LEFT OUTER JOIN (
SELECT [date] , ROW_NUMBER() OVER (ORDER BY [date]) - 1 AS [e]
FROM #groupedDates) AS [end]
ON [start].[s] = [end].[e]
) AS temp
SELECT [ta].[id], [ta].[startDate] AS [date], temp.[group]
FROM #tempA AS [ta]
INNER JOIN (
SELECT [t1].[id], SUM([t2].[changeGroup]) as [group]
FROM #tempA AS [t1]
INNER JOIN #tempA AS [t2] ON [t1].[id] >= [t2].[id]
GROUP BY [t1].[id], [t1].[changeGroup]) AS temp
ON [ta].[id] = temp.[id] + 1
ORDER BY [ta].[id]
Run Code Online (Sandbox Code Playgroud)
可能会有更好的方法来做到这一点,但我以前使用过这种方法