SQL分组日期范围到行

时间:2015-06-10 06:25:48

标签: sql sql-server sql-server-2012 date-range

我尝试在数据集中找到给定的日期范围,并将其划分为范围中每天的唯一行(例如下面的示例)。在SQL中执行相反的操作非常简单,但我正在努力实现所需的查询输出。

开始数据:

ITEM    START_DATE  END_DATE
A       1/1/2015    1/5/2015
B       2/5/2015    2/7/2015

所需的查询输出:

 ITEM   DATE_COVERED
 A      1/1/2015
 A      1/2/2015
 A      1/3/2015
 A      1/4/2015
 A      1/5/2015
 B      2/5/2015
 B      2/6/2015
 B      2/7/2015

4 个答案:

答案 0 :(得分:2)

最快的方式是一些计数表:

DECLARE @t TABLE
    (
      ITEM CHAR(1) ,
      START_DATE DATE ,
      END_DATE DATE
    )
INSERT  INTO @t
VALUES  ( 'A', '1/1/2015', '1/5/2015' ),
        ( 'B', '2/5/2015', '2/7/2015' )



;WITH cte AS(SELECT -1 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) d FROM
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t1(n) CROSS JOIN
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t2(n) CROSS JOIN
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t3(n) CROSS JOIN
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t4(n))

SELECT t.ITEM, ca.DATE_COVERED FROM @t t
CROSS APPLY(SELECT DATEADD(dd, d, t.START_DATE) AS DATE_COVERED 
            FROM cte 
            WHERE DATEADD(dd, d, t.START_DATE) BETWEEN t.START_DATE AND t.END_DATE) ca   
ORDER BY t.ITEM, ca.DATE_COVERED

答案 1 :(得分:1)

查询:

<强> SQLFiddleExample

SELECT t.ITEM, 
        DATEADD(day,n.number, t.START_DATE) AS DATE_COVERED
FROM Table1 t,
(SELECT number
FROM master..spt_values
WHERE [type] = 'P') n
WHERE START_DATE <= DATEADD(day,n.number, t.START_DATE)
AND END_DATE >= DATEADD(day,n.number, t.START_DATE)

结果:

| ITEM | DATE_COVERED |
|------|--------------|
|    A |   2015-01-01 |
|    A |   2015-01-02 |
|    A |   2015-01-03 |
|    A |   2015-01-04 |
|    A |   2015-01-05 |
|    B |   2015-02-05 |
|    B |   2015-02-06 |
|    B |   2015-02-07 |

答案 2 :(得分:1)

注意:这仅在startdate和enddate之间的差异最大为2047天时才有效(master..spt_values仅允许0..2047范围的值)

 select item, dateadd(d,v.number,d.start_date) adate
 from begindata d
 join master..spt_values v on v.type='P'
           and v.number between 0 and datediff(d, start_date, end_date)
 order by adate;

我想说我自己这样做但是我从this获得了代码

这是您预期的result

的小提琴

答案 3 :(得分:0)

尝试这个......

CREATE TABLE Table1
    ([ITEM] varchar(1), [START_DATE] date, [END_DATE] date)
;

INSERT INTO Table1
    ([ITEM], [START_DATE], [END_DATE])
VALUES    ('A', '2015-01-01', '2015-01-05'), ('B', '2015-02-05', 2015-02-07');

WITH    Days
          AS ( SELECT ITEM,  START_DATE AS [Date], 1 AS [level] from Table1
               UNION ALL
               SELECT  TABLE1.ITEM, DATEADD(DAY, 1, [Date]), [level] + 1
               FROM     Days,Table1
               WHERE  DAYS.ITEM=TABLE1.ITEM AND  [Date] < END_DATE )
     SELECT distinct [Date]
     FROM   Days

DEMO