在雪花视图中将日期范围拆分为新记录

Split date range into new records in Snowflake View

我有一个 table,它由开始日期和结束日期组成,我需要将记录拆分为按天计算的数据,这需要放在视图中。

| PersonID  | CompanyID    | Start_DT    | End_DT    |
|-----------|--------------|-------------|-----------|
| A12       | abc          | 05-01-2020  | 05-03-2020|
| B23       | def          | 06-08-2020  | 06-14-2020|

| PersonID  | CompanyID    | New_DT      |
|-----------|--------------|-------------|
| A12       | abc          | 05-01-2020  | ==> A12 Start Date is 05-01-2020 and End Date is 05-03-2020. So there are 3 records generated in New_DT
| A12       | abc          | 05-02-2020  | 
| A12       | abc          | 05-03-2020  | 
| B23       | def          | 06-08-2020  | 
| B23       | def          | 06-09-2020  | 
| B23       | def          | 06-10-2020  | 
| B23       | def          | 06-11-2020  | 
| B23       | def          | 06-12-2020  | 
| B23       | def          | 06-13-2020  | 
| B23       | def          | 06-14-2020  |   

如何在 View 中实现此目的?

您可以使用递归 CTE:

with cte as (
      select PersonID, CompanyID, Start_DT as new_dt, End_DT  
      from t
      union all
      select PersonID, CompanyID, dateadd(day, 1, new_dt), End_DT  
      from cte
      where new_dt < end_dt
     )
select PersonID, CompanyID, new_dt
from cte
option (maxrecursion 0);

如果您的经期超过100天,那么您需要添加option (maxrecursion 0)

Here 是一个 db<>fiddle.

要填写日期,需要一种生成行的方法。一种已知快速有效的方法是 tally 或数字 table。像这样

Tally tvf(生成大量行,足以填充 BIGINT)

drop function if exists [dbo].[fnNumbers];
go
create function [dbo].[fnNumbers](
  @zero_or_one   bit, 
  @n             bigint)
returns table with schemabinding as return
with n(n) as (select null from (values (1),(2),(3),(4)) n(n))
select 0 n where @zero_or_one = 0
union all
select top(@n) row_number() over(order by (select null)) n
from n na, n nb, n nc, n nd, n ne, n nf, n ng, n nh,
     n ni, n nj, n nk, n nl, n nm, n np, n nq, n nr;
go

查询

select it.PersonID, it.CompanyID, da.dt
from #t it
     cross apply
     dbo.fnNumbers(0, datediff(day, Start_DT, End_DT)) fn
     cross apply
     (select dateadd(day, fn.n, it.Start_DT) dt) da;

输出

PersonID    CompanyID   dt
A12         abc         2020-05-01
A12         abc         2020-05-02
A12         abc         2020-05-03
B23         def         2020-06-08
B23         def         2020-06-09
B23         def         2020-06-10
B23         def         2020-06-11
B23         def         2020-06-12
B23         def         2020-06-13
B23         def         2020-06-14