Sql 扩大日期范围

Sql 扩大日期范围,sql,date,snowflake-cloud-data-platform,recursive-query,Sql,Date,Snowflake Cloud Data Platform,Recursive Query,我想扩展下表中的日期范围。最终结果应该是结果表。我知道这可以在sql中使用dateadd和CTE来完成。但是,我无法获得正确的联接以获得如下所示的结果。请提出可能的解决办法 我使用的查询如下所示: WITH Calendar AS ( select DATEADD(day, 1, '2019-08-01') as date UNION ALL select DATEADD(day, 1, date) from Calendar where date <=

我想扩展下表中的日期范围。最终结果应该是结果表。我知道这可以在sql中使用dateadd和CTE来完成。但是,我无法获得正确的联接以获得如下所示的结果。请提出可能的解决办法

我使用的查询如下所示:

WITH Calendar AS  
(  
  select DATEADD(day, 1, '2019-08-01') as date
  UNION ALL  
  select DATEADD(day, 1, date) 
  from Calendar 
  where date <= '2019-08-05'  
)
SELECT o.Column1,o.Column2,o.Column3, calendar.date
FROM OriginalTable o
 inner join calendar
on calendar.date=o.Column3

它给我的结果是原始表格。我使用了各种选项,但它给了我其他不正确的结果。

您的查询的直接问题是,您应该在外部查询中使用左连接,而不是内部连接,因此不会过滤掉缺少的日期

然而,这可能还不够。您还需要跟踪原始值,以便将它们放在新生成的行中

直接从递归查询生成行可能更简单:

with cte as (
    select column1, column2, column3, lead(column3) over(order by column3) lead_column3
    from original table
    union all
    select column1, column2, dateadd(day, 1, column3), lead_column3
    from cte
    where dateadd(day, 1, column3) < lead_column3
)
select * from cte

查询的直接问题是,在外部查询中应该使用左连接而不是内部连接,因此不会过滤掉缺失的日期

然而,这可能还不够。您还需要跟踪原始值,以便将它们放在新生成的行中

直接从递归查询生成行可能更简单:

with cte as (
    select column1, column2, column3, lead(column3) over(order by column3) lead_column3
    from original table
    union all
    select column1, column2, dateadd(day, 1, column3), lead_column3
    from cte
    where dateadd(day, 1, column3) < lead_column3
)
select * from cte

正如我在@GMB的帖子中提到的,递归解决方案存在一个潜在的问题,递归深度是有限的;默认为100。为了避免这一点,一个替代解决方案是使用生成器函数,尽管需要两个步骤,这对于OP的用例来说可能是不可接受的

SET RC = (SELECT DATEDIFF(DAY, COLUMN3, LEAD(COLUMN3) OVER (ORDER BY COLUMN3)) AS DAY_GAP FROM OriginalTable ORDER BY DAY_GAP DESC NULLS LAST LIMIT 1)
;

WITH X1 AS (
  SELECT *
        ,LEAD(OT.COLUMN3) OVER (ORDER BY COLUMN3) AS COLUMN3_NEXT
    FROM OriginalTable OT
)
,X2 AS (
  SELECT SEQ8() AS DAY_OFFSET
    FROM TABLE(GENERATOR(ROWCOUNT => $RC))
)
SELECT X1.COLUMN1
      ,X1.COLUMN2
      ,DATEADD(DAY, X2.DAY_OFFSET, X1.COLUMN3) AS COLUMN3
  FROM X1
       CROSS JOIN X2
 WHERE (DATEADD(DAY, X2.DAY_OFFSET, X1.COLUMN3) < X1.COLUMN3_NEXT OR X2.DAY_OFFSET = 0)
;

正如我在@GMB的帖子中提到的,递归解决方案存在一个潜在的问题,递归深度是有限的;默认为100。为了避免这一点,一个替代解决方案是使用生成器函数,尽管需要两个步骤,这对于OP的用例来说可能是不可接受的

SET RC = (SELECT DATEDIFF(DAY, COLUMN3, LEAD(COLUMN3) OVER (ORDER BY COLUMN3)) AS DAY_GAP FROM OriginalTable ORDER BY DAY_GAP DESC NULLS LAST LIMIT 1)
;

WITH X1 AS (
  SELECT *
        ,LEAD(OT.COLUMN3) OVER (ORDER BY COLUMN3) AS COLUMN3_NEXT
    FROM OriginalTable OT
)
,X2 AS (
  SELECT SEQ8() AS DAY_OFFSET
    FROM TABLE(GENERATOR(ROWCOUNT => $RC))
)
SELECT X1.COLUMN1
      ,X1.COLUMN2
      ,DATEADD(DAY, X2.DAY_OFFSET, X1.COLUMN3) AS COLUMN3
  FROM X1
       CROSS JOIN X2
 WHERE (DATEADD(DAY, X2.DAY_OFFSET, X1.COLUMN3) < X1.COLUMN3_NEXT OR X2.DAY_OFFSET = 0)
;

Outer join a help calendar table/cte.Outer join a help calendar table/cte。这是一个非常好的解决方案。注意:从技术上讲,原始表应该是可原创的,select*应该是select column1、column2、column3,但请注意,实际上存在一个递归限制,默认为100,因此,只有当两个日期之间的最大间隔不超过这个限制时,它才起作用。要看到这一点,请尝试将最后一行更改为b,z,'8/12/2021'。这是一个奇妙而优雅的解决方案注意:从技术上讲,原始表应该是可原创的,select*应该是select column1,column2,column3,但请注意,实际上存在一个递归限制,默认为100,因此,只有当两个日期之间的最大间隔不超过这个限制时,它才起作用。要看到这一点,请尝试将最后一行更改为b,z,'8/12/2021'。GMB我确实尝试了不同类型的连接,但没有成功。您的解决方案非常简单优雅。尚未尝试过您的解决方案。将尝试并恢复。谢谢@GMB我确实尝试过不同类型的连接,但没有成功。您的解决方案非常简单优雅。尚未尝试过您的解决方案。将尝试并恢复。谢谢