在SQL中查找所有连续日期

时间:2014-11-12 19:32:57

标签: sql sql-server

我无法确定查询只显示SQL中的连续日期(最少3个)。在搜索堆栈交换之后,有一些解决方案,但我无法让它们按照我想要的方式工作。请考虑下表(为了安全性而更改了实际数据和表名称):

code         food         date   
------       ------      ------
ABC123       Sushi       09/28/2013
ABC123       Sushi       09/29/2013
ABC123       Sushi       09/30/2013
ABC123       Sushi       10/01/2013
BCD234       Burger      10/05/2013
BCD234       Burger      10/10/2013
BCD234       Burger      10/27/2013
BCD234       Fries       10/05/2013
BCD234       Fries       10/06/2013
BCD234       Fries       10/10/2013
CDE345       Steak       10/15/2013
CDE345       Steak       10/16/2013
CDE345       Steak       10/17/2013
CDE345       Steak       10/19/2013
CDE345       Steak       10/20/2013
DEF456       Pasta       09/05/2013
DEF456       Pasta       09/06/2013
DEF456       Pasta       09/10/2013
DEF456       Burrito     09/09/2013
DEF456       Burrito     09/10/2013
DEF456       Burrito     09/11/2013

只应显示此内容:

code         food         date   
------       ------      ------
ABC123       Sushi       09/28/2013
ABC123       Sushi       09/29/2013
ABC123       Sushi       09/30/2013
ABC123       Sushi       10/01/2013
CDE345       Steak       10/15/2013
CDE345       Steak       10/16/2013
CDE345       Steak       10/17/2013
DEF456       Burrito     09/09/2013
DEF456       Burrito     09/10/2013
DEF456       Burrito     09/11/2013

考虑到代码,食物和日期在任何给定时间都是可变的,如上所示创建结果的查询是什么?查询应该只找到每个给定代码和食物对(键)的最少3个连续日期。

我尝试了解Stack Exchange上的一个查询:

select code, grp, count(*) as NumInSequence, min(date), max(date)
from (select t.*, (date - row_number() over (partition by code order by date)) as grp
  from #TempTable t
    ) t
group by code, grp

...但是我收到有关将数据类型varchar转换为bigint的错误(这可能是由于代码是字母数字而不是常规的int ID)。另外,我假设上面的代码无论如何都不能给我确切的结果。

请告知,谢谢你的帮助。

3 个答案:

答案 0 :(得分:3)

您可以使用窗口功能执行此操作。您可以通过从日期中减去row_number()来识别连续日期组。使用该组,您可以计算行数,并仅选择具有3行或更多行的行:

select code, food, date
from (select t.*, count(*) over (partition by code, food, grp) as cnt
      from (select t.*,
                   dateadd(day, - row_number() over (partition by code, food order by date), date) as grp
            from #temptable t
           ) t
     ) t
where cnt >= 3;

答案 1 :(得分:0)

    you can create temp table with two additional columns
    columns-id (identify(1,1) and delta_date.
    and insert into it the 'old table'.
    the column 'delta_date' is results of date(column2)-date(column1) by day
    (and so for all rows respectively).
    now you can select all rows where 'delta_date'=1 and count 'delta_date'>=3

答案 2 :(得分:0)

对原始代码进行简单更改可使其正常工作:

select code, FOOD,grp, count(*) as NumInSequence, min([date]) AS MIN_date, max([date]) AS MAX_Date
from (select CODE,FOOD,[DATE],(DATEDIFF(D,'1/1/1900',[date])) - row_number() over (partition by code,FOOD order by [date]) as grp from @T t ) t
group by code, FOOD, grp 
HAVING count(*) >= 3
order by code

通过从某个基准日期“1/1/1900”开始的天数将内部日期转换为int,将创建一个现在可在现有代码中使用的int值! 此外,我将Food Group添加到row_number()部分,以仅查找包含用户/项目组合的匹配。