Get a list of dates between two dates using a function

前端 未结 21 1334
天涯浪人
天涯浪人 2020-11-22 06:25

My question is similar to this MySQL question, but intended for SQL Server:

Is there a function or a query that will return a list of days between two dates? For exa

21条回答
  •  没有蜡笔的小新
    2020-11-22 06:57

    Try something like this:

    CREATE FUNCTION dbo.ExplodeDates(@startdate datetime, @enddate datetime)
    returns table as
    return (
    with 
     N0 as (SELECT 1 as n UNION ALL SELECT 1)
    ,N1 as (SELECT 1 as n FROM N0 t1, N0 t2)
    ,N2 as (SELECT 1 as n FROM N1 t1, N1 t2)
    ,N3 as (SELECT 1 as n FROM N2 t1, N2 t2)
    ,N4 as (SELECT 1 as n FROM N3 t1, N3 t2)
    ,N5 as (SELECT 1 as n FROM N4 t1, N4 t2)
    ,N6 as (SELECT 1 as n FROM N5 t1, N5 t2)
    ,nums as (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as num FROM N6)
    SELECT DATEADD(day,num-1,@startdate) as thedate
    FROM nums
    WHERE num <= DATEDIFF(day,@startdate,@enddate) + 1
    );
    

    You then use:

    SELECT *
    FROM dbo.ExplodeDates('20090401','20090531') as d;
    

    Edited (after the acceptance):

    Please note... if you already have a sufficiently large nums table then you should use:

    CREATE FUNCTION dbo.ExplodeDates(@startdate datetime, @enddate datetime)
    returns table as
    return (
    SELECT DATEADD(day,num-1,@startdate) as thedate
    FROM nums
    WHERE num <= DATEDIFF(day,@startdate,@enddate) + 1
    );
    

    And you can create such a table using:

    CREATE TABLE dbo.nums (num int PRIMARY KEY);
    INSERT dbo.nums values (1);
    GO
    INSERT dbo.nums SELECT num + (SELECT COUNT(*) FROM nums) FROM nums
    GO 20
    

    These lines will create a table of numbers containing 1M rows... and far quicker than inserting them one by one.

    You should NOT create your ExplodeDates function using a function that involves BEGIN and END, as the Query Optimizer becomes unable to simplify the query at all.

提交回复
热议问题