2

There are some quite similar questions, but not the same. I have to solve the next problem: From table with such structure

| DATE_FROM  | DATE_TO    |
|------------|------------|
| 2010-05-17 | 2010-05-19 |
| 2017-01-02 | 2017-01-04 |
| 2017-05-01 | NULL       |
| 2017-06-12 | NULL       | 

I need to get a list like the one below

| DATE_LIST  |
|------------|
| 2010-05-17 |
| 2010-05-18 |
| 2010-05-19 |
| 2017-01-02 |
| 2010-01-03 |
| 2010-01-04 |
| 2017-05-01 |
| 2017-06-12 |

How can I get it with SQL? SQL Server 2016.

1
  • What ahve you tried so far? Commented May 29, 2017 at 14:07

3 Answers 3

3

Another option is with a CROSS APPLY and an ad-hoc tally table

Select Date_List=B.D 
 from YourTable A
 Cross Apply ( 
                Select Top (DateDiff(DAY,[DATE_FROM],IsNull([DATE_TO],[DATE_FROM]))+1) D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),[DATE_FROM]) 
                 From  master..spt_values n1,master..spt_values n2 
             ) B

Returns

Date_List
2010-05-17
2010-05-18
2010-05-19
2017-01-02
2017-01-03
2017-01-04
2017-05-01
2017-06-12
Sign up to request clarification or add additional context in comments.

2 Comments

Note that master..spt_values is not documented and doesn't exist at all in Azure SQL database. A permanent user-defined number table would be better.
@DanGuzman Agreed, Clearly a Tally/Calendar table would be the way to go. but that said, any table of respectible size would do. There is no reference to any field name
3

One method uses a recursive CTE:

with cte as (
      select date_from as date_list, date_to
      from t
      union all
      select dateadd(day, 1, date_from), date_to
      from cte
      where date_from < date_to
     )
select date_list
from cte;

By default, the recursive CTE is limited to a recursive depth of 100 (and then it returns an error). That works for spans of up to 100 days. You can remove the limit with OPTION (MAXRECURSION 0).

2 Comments

Maybe I'm mistaken, but your SQL-code returns only 1-st column
@ЕвгенийМ . . . No, it would have generated an error. I need to selectd the correct column.
2

Although you could create the date range on the fly in your query, consider creating a permanent calendar table. This will provide better performance and can be extended with other attributes like day of week, fiscal quarter, etc. You can find many examples of loading such a table with an internet search.

Below is an example with 40 years of dates.

--example calendar table load script
CREATE TABLE dbo.Calendar(
    CalendarDate date NOT NULL
        CONSTRAINT PK_Calendar PRIMARY KEY
    );
WITH 
     t4 AS (SELECT n FROM (VALUES(0),(0),(0),(0)) t(n))
    ,t256 AS (SELECT 0 AS n FROM t4 AS a CROSS JOIN t4 AS b CROSS JOIN t4 AS c CROSS JOIN t4 AS d)
    ,t64k AS (SELECT ROW_NUMBER() OVER (ORDER BY (a.n)) AS num FROM t256 AS a CROSS JOIN t256 AS b)
INSERT INTO dbo.Calendar WITH(TABLOCKX)
SELECT DATEADD(day, num, '20000101')
FROM t64k
WHERE DATEADD(day, num, '20000101') < '20400101'
GO
DECLARE @example TABLE(
     DATE_FROM date NOT NULL
    ,DATE_TO  date NULL
    );
GO

--example query
INSERT INTO @example VALUES
      ('2010-05-17', '2010-05-19')
    , ('2017-01-02', '2017-01-04')
    , ('2017-05-01', NULL)
    , ('2017-06-12', NULL)
SELECT
     c.CalendarDate
FROM @example AS e
JOIN dbo.Calendar AS c ON
    c.CalendarDate BETWEEN e.DATE_FROM AND COALESCE(e.DATE_TO, e.DATE_FROM);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.