SQL - 按日期范围对行进行分组,行中包含连续值

时间:2016-04-21 15:26:54

标签: sql sql-server-2008

注意:我已经看到了答案 SQL Group by Date RangeGroup rows by contiguous date ranges for groups of values并且都提到了row_number()的使用。即使借助这些答案,我也无法弄清楚这一点,经过一整天的沉思和研究后,我终于屈服了,来到这里寻求帮助。 编辑:既然我理解了戈登林诺夫的回答,我意识到我的问题与我联系的其他人有多么相似,并且因为我不理解答案而为近乎重复的帖子道歉。

我有一个输入表,其中包含对客户进行查询的“结果”的历史记录,该结果通过每年每个月的最新结果合并到一个视图中。该视图(示意性地)看起来像这样:

client_id | month |  year  |  result  
1            2       2016       Y
2            3       2016       N     
1            4       2016       Y
1            5       2016       N
2            4       2016       N

所以我试图输出这样的结果视图:

client_id | start_month |  start_year |  end_month  |  end_year  |  result
1                2           2016            3           2016          Y
2                3           2016          (NULL)        (NULL)        N    
1                5           2016          (NULL)        (NULL)        N          

我陷入困境的原因:

  1. 对row_number()的大多数解释以及它在这里的应用方法都没有通过我
  2. 我正在使用而不是日期值,从DATEPART()调用在另一个视图中最初创建的月 - 月类型查询派生的列,因为这是SQL 2008,我无法将它们转回日期(如使用DATEFROMPARTS()
  3. 轻松实现4-1-2016而不是4,2016

1 个答案:

答案 0 :(得分:3)

您的数据与其他问题中的数据完全相同 - 除了将值拆分为两列这一事实外。

要了解正在发生的事情,请从此查询开始:

select t.*,
       row_number() over (partition by client_id order by start_year, start_month) as seqnum_client,
       (start_year * 12 + start_month) as month_counter
from t
order by client_id, start_year, start_Month;

然后取最后两列的差异。您会注意到这些在连续的时间段内是不变的。这成为分组的关键。

我将留下这个版本:

select client_id,
       min(start_year * 100 + start_month) as start_yyyymm,
       max(start_year * 100 + start_month) as end_yyyymm,
       max(result) as result
from (select t.*,
           row_number() over (partition by client_id order by start_year, start_month) as seqnum_client,
           (start_year * 12 + start_month as month_counter
     from t
    ) t
group by client_id, (seqnum_client - month_counter)
order by client_id, max(seqnum_client);

注意:我不确定Result的确切逻辑,但max()会返回问题中的值。