扩大日期范围
Expanding Date Ranges
我想扩大下面“原始 Table”中的日期范围。最终结果应该是“Resultant Table”。我知道这可以在 sql 中使用 dateadd 和 ctes 完成。但是,我无法获得如下所示的结果的连接权。请提出可能的解决方案。
我使用的查询是这样的:
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
它给我的结果是原来的table。我试过各种选项,它给了我其他不正确的结果。
您查询的直接问题是您应该在外部查询中使用 left join
而不是 inner join
,因此不会过滤掉“缺失”日期。
然而,这可能还不够。您还需要跟踪原始值,以便将它们放入新生成的行中。
直接从递归查询生成行可能更简单:
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 的 post 中提到的,递归解决方案存在潜在问题(递归深度有限;默认为 100)。为了避免这种情况,一种替代解决方案是改用 GENERATOR 函数(尽管这需要 2 个步骤,这对于 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)
;
我想扩大下面“原始 Table”中的日期范围。最终结果应该是“Resultant Table”。我知道这可以在 sql 中使用 dateadd 和 ctes 完成。但是,我无法获得如下所示的结果的连接权。请提出可能的解决方案。
我使用的查询是这样的:
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
它给我的结果是原来的table。我试过各种选项,它给了我其他不正确的结果。
您查询的直接问题是您应该在外部查询中使用 left join
而不是 inner join
,因此不会过滤掉“缺失”日期。
然而,这可能还不够。您还需要跟踪原始值,以便将它们放入新生成的行中。
直接从递归查询生成行可能更简单:
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 的 post 中提到的,递归解决方案存在潜在问题(递归深度有限;默认为 100)。为了避免这种情况,一种替代解决方案是改用 GENERATOR 函数(尽管这需要 2 个步骤,这对于 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)
;