【问题标题】:How to create recursive query to get all dates between two dates如何创建递归查询以获取两个日期之间的所有日期
【发布时间】:2016-06-15 12:22:13
【问题描述】:

我想获取两个日期 arrival dateleaving date 之间的所有日期。

我尝试了递归查询,但没有成功。

;with dates as ( 
SELECT GuestID, ArrivalDate as reserveddate 
from dbo.Guest 
union all 
SELECT GuestID, dateadd (day,1,dbo.Guest. ArrivalDate) as reserveddate 
from dbo.Guest 
where dateadd (day,1,dbo.Guest. ArrivalDate) <dbo.Guest.leavingate
) 

SELECT * 
from dates 
option (maxrecursion 0)

【问题讨论】:

  • 我试过了,但它不起作用。日期为 (SELECT GuestID, ArrivalDate as reserveddate from dbo.Guest union all SELECT GuestID, dateadd (day,1,dbo.Guest.ArrivalDate) as reserveddate from dbo.Guest where dateadd (day,1,dbo.Guest. ArrivalDate)
  • 您需要在查询的递归部分将dates 加入dbo.Guest
  • 检查我的答案:)
  • 它也返回相同的结果.. union 适用于第一次添加和递归不起作用
  • 那么,您需要什么?显示数据样本以及您需要从中获得什么。

标签: sql sql-server database plsqldeveloper


【解决方案1】:

你需要递归 CTE:

DECLARE  @arrival_date date = '2016-01-01',
         @leaving_date date = '2016-02-01'

;WITH cte AS (
SELECT @arrival_date as date_
UNION ALL
SELECT CAST(DATEADD(day,1,date_) as date)
FROM cte
WHERE date_ < @leaving_date
)

SELECT *
FROM cte
OPTION (MAXRECURSION 0)

输出:

date_
2016-01-01
2016-01-02
2016-01-03
...
2016-01-30
2016-01-31
2016-02-01

EDIT1

根据您的样本:

;WITH cte AS (
SELECT GuestID, CAST(ArrivalDate as date) as date_
FROM Guests
UNION ALL
SELECT c.GuestID, CAST(DATEADD(day,1,date_) as date)
FROM cte c
INNER JOIN Guests g
    ON g.GuestID = c.GuestID
WHERE date_ < g.LeavingDate
)

SELECT *
FROM cte
ORDER BY GuestID, date_
OPTION (MAXRECURSION 0)

EDIT2

;WITH Guests AS (
SELECT  1 as GuestID,
        '2016-01-01' ArrivalDate,
        '2016-01-05' LeavingDate
UNION ALL
SELECT  2 ,
        '2016-06-17',
        '2016-06-20'
), cte AS (
SELECT GuestID, CAST(ArrivalDate as date) as date_
FROM Guests
UNION ALL
SELECT c.GuestID, CAST(DATEADD(day,1,date_) as date)
FROM cte c
INNER JOIN Guests g
    ON g.GuestID = c.GuestID
WHERE date_ < g.LeavingDate
)

SELECT *
FROM cte
ORDER BY GuestID, date_
OPTION (MAXRECURSION 0)

输出:

GuestID date_
1   2016-01-01
1   2016-01-02
1   2016-01-03
1   2016-01-04
1   2016-01-05
2   2016-06-17
2   2016-06-18
2   2016-06-19
2   2016-06-20

【讨论】:

  • 对不起,我删除了它
【解决方案2】:

我对这种类型的偏好是使用计数表。我对每个看起来像这样的系统都有一个看法。

create View [dbo].[cteTally] as

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
select N from cteTally
GO

这样一来,我就可以随时拥有一个触手可及的计数表。您可以在此处阅读有关计数表以及它们如何替换循环的更多信息。 http://www.sqlservercentral.com/articles/T-SQL/62867/

要解决您当前的问题,这变得相当简单。首先,我们需要一个表格和一些示例数据。

create table #Guest
(
    GuestID int identity
    , ArrivalDate date
    , DepartureDate date
)

insert #Guest
select '2016-06-01', '2016-06-15' union all
select '2016-07-01', '2016-07-12'

这就是计数表真正发挥作用的地方。为您的挑战生成输出就像这段代码一样简单。

SELECT GuestID
    , ArrivalDate 
    , DepartureDate
    , DATEADD(Day, N - 1, ArrivalDate) as EachDate
from #Guest g
join cteTally t on t.N <= DATEDIFF(day, ArrivalDate, DepartureDate) + 1
order by GuestID
    , EachDate

与递归 cte 相比,这种方法的另一大优势是您使用的是所谓的三角连接,可能会导致一些性能挑战。这是有关三角形连接的更多信息。 http://www.sqlservercentral.com/articles/T-SQL/61539/

【讨论】:

    【解决方案3】:

    试试这个

        DECLARE @DateFrom DateTime = DATEADD(DAY,DATEDIFF(DAY,0,GETDATE())-5,0)
        DECLARE @DateTo DateTime = CONVERT(DATE,GETDATE())
    
        ;WITH Numbers (Number) AS (
             SELECT row_number() OVER (ORDER BY object_id)
             FROM sys.all_objects
        )
    
        SELECT  dateadd(DAY, number-1, @DateFrom)           
        FROM    Numbers
        WHERE   number <= datediff(DAY, @DateFrom-1, @DateTo-1)
    

    您可以通过在 select dateadd 和 where datediff 中将 DAY 更改为 WEEK、MONTH、YEAR 等来更改日期间隔

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-09
      • 1970-01-01
      • 2013-01-05
      • 2017-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-08
      相关资源
      最近更新 更多