根据组确定日期范围

时间:2014-10-31 15:58:28

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

在编写以下格式的Sql查询时需要帮助:

来源数据:

Field1    Field2  last_update
1234      ABC     2013-01-01
1234      ABC     2013-01-02
1234      ABC     2013-01-03
1234      ABC     2013-01-06
2345      ABC     2013-01-07   -- Field1 is different from prev. row, new group
2345      ABC     2013-01-08
2345      ABC     2013-01-09
1234      ABC     2013-01-10   -- Field1 is different from prev. row, new group
1234      ABC     2013-01-11
2345      ABC     2013-01-12   -- Field1 is different from prev. row, new group

结果集数据应采用以下格式:

Field1  Field2  start_date  stop_date
1234    ABC     2013-01-01  2013-01-06
2345    ABC     2013-01-07  2013-01-09
1234    ABC     2013-01-10  2013-01-11
2345    ABC     2013-01-12  2013-01-12

生成结果的逻辑基于last_updatestart_date是该组的min(last_update)stop_datemax(last_update)。如果Field1与上一行不同,则会开始另一个分组。

1 个答案:

答案 0 :(得分:6)

看起来您想要在数据中找到连续的序列。这通常被称为 gap-and-islands 问题,一种解决方案是使用row_number()函数来确定这样的组(岛):

SELECT 
    Field1, 
    Field2, 
    Start_date = MIN(last_update),
    Stop_date = MAX(last_update)
FROM (
    SELECT 
       Field1, Field2, last_update,
       ROW_NUMBER() OVER (ORDER BY last_update) -
       ROW_NUMBER() OVER (PARTITION BY Field1, Field2 ORDER BY last_update) grp
    FROM [Source Data]
    ) A
GROUP BY Field1, Field2, grp
ORDER BY MIN(last_update)

使用您的样本数据,结果就是:

Field1      Field2 Start_date Stop_date
----------- ------ ---------- ----------
1234        ABC    2013-01-01 2013-01-06
2345        ABC    2013-01-07 2013-01-09
1234        ABC    2013-01-10 2013-01-11
2345        ABC    2013-01-12 2013-01-12

该解决方案来自 SQL Server MVP Deep Dives 系列中的一本书,但我不记得是哪一个以及要归功于谁。