插入虚拟行以将缺失值填充到 SQL Table
Insert dummy rows to fill missing values into a SQL Table
我有这个 SQL 服务器 table table1
我想用每个帐户的虚拟行填充到最近的上个月结束日期期间,例如现在到 2021- 06-30.
在此示例中,acct 1 有 n 行,以 2020-05-31 结束,我想为 acct
和 amt
插入具有相同值的虚拟行 begin_date
和 end_date
增加 1 个月,直到 06-30-2021。
假设 acct
2 已经在 06-30-2021 结束,因此不需要插入虚拟行。
acct,amt,begin_date,end_date
1 , 10, 2020-04-01, 2020-04-30
1 , 10, 2020-05-01, 2020-05-31
2 , 50, 2021-05-01, 2021-05-31
2 , 50, 2021-06-01, 2021-06-30
因此,对于帐户 1,我希望从 2020-05-31 的最后一个时期到上个月末(现在是 06-30-2021)插入 n 行,我希望保留 amt 和帐户相同的。所以它看起来像下面这样:
acct,amt,begin_date,end_date
1 , 10, 2020-04-01, 2020-04-30
1 , 10, 2020-05-01, 2020-05-31
1 , 10, 2020-06-01, 2020-06-30
1 , 10, 2020-07-01, 2020-07-31
.............................
.............................
1 , 10, 2021-06-01, 2021-06-30
根据一些数据分析,我意识到我需要解决方案的另一个条件。假设另一列 type
添加到 table1
。因此 acct
和 type
将是标识每个相关行的复合键,因此 acct 2 type A 和 acct 2 type B 不相关。所以我们有更新的 table:
acct,type,amt,begin_date,end_date
1, A, 10, 2020-04-01, 2020-04-30
1, A, 10, 2020-05-01, 2020-05-31
2, A, 50, 2021-05-01, 2021-05-31
2, A, 50, 2021-06-01, 2021-06-30
2, B, 50, 2021-01-01, 2021-01-31
2, B, 50, 2021-02-01, 2021-02-28
我现在需要为 acct 2 type B 创建到 2021-06-30 的虚拟行。我们已经知道 acct 2 类型 A 可以,因为它已经有行到 2021-06-30
您可以使用递归 CTE 生成行:
with cte as (
select acct, amt,
dateadd(day, 1, end_date) as begin_date,
eomonth(dateadd(day, 1, end_date)) as end_date
from (select t.*,
row_number() over (partition by acct order by end_date desc) as seqnum
from t
) t
where seqnum = 1 and end_date < '2021-06-30'
union all
select acct, amt, dateadd(month, 1, begin_date),
eomonth(dateadd(month, 1, begin_date))
from cte
where begin_date < '2021-06-01'
)
select *
from cte;
然后您可以使用 insert
将这些行插入 table。或者,如果您只想要包含所有行的结果集,请使用 union all
。
Here 是一个 db<>fiddle.
我有这个 SQL 服务器 table table1
我想用每个帐户的虚拟行填充到最近的上个月结束日期期间,例如现在到 2021- 06-30.
在此示例中,acct 1 有 n 行,以 2020-05-31 结束,我想为 acct
和 amt
插入具有相同值的虚拟行 begin_date
和 end_date
增加 1 个月,直到 06-30-2021。
假设 acct
2 已经在 06-30-2021 结束,因此不需要插入虚拟行。
acct,amt,begin_date,end_date
1 , 10, 2020-04-01, 2020-04-30
1 , 10, 2020-05-01, 2020-05-31
2 , 50, 2021-05-01, 2021-05-31
2 , 50, 2021-06-01, 2021-06-30
因此,对于帐户 1,我希望从 2020-05-31 的最后一个时期到上个月末(现在是 06-30-2021)插入 n 行,我希望保留 amt 和帐户相同的。所以它看起来像下面这样:
acct,amt,begin_date,end_date
1 , 10, 2020-04-01, 2020-04-30
1 , 10, 2020-05-01, 2020-05-31
1 , 10, 2020-06-01, 2020-06-30
1 , 10, 2020-07-01, 2020-07-31
.............................
.............................
1 , 10, 2021-06-01, 2021-06-30
根据一些数据分析,我意识到我需要解决方案的另一个条件。假设另一列 type
添加到 table1
。因此 acct
和 type
将是标识每个相关行的复合键,因此 acct 2 type A 和 acct 2 type B 不相关。所以我们有更新的 table:
acct,type,amt,begin_date,end_date
1, A, 10, 2020-04-01, 2020-04-30
1, A, 10, 2020-05-01, 2020-05-31
2, A, 50, 2021-05-01, 2021-05-31
2, A, 50, 2021-06-01, 2021-06-30
2, B, 50, 2021-01-01, 2021-01-31
2, B, 50, 2021-02-01, 2021-02-28
我现在需要为 acct 2 type B 创建到 2021-06-30 的虚拟行。我们已经知道 acct 2 类型 A 可以,因为它已经有行到 2021-06-30
您可以使用递归 CTE 生成行:
with cte as (
select acct, amt,
dateadd(day, 1, end_date) as begin_date,
eomonth(dateadd(day, 1, end_date)) as end_date
from (select t.*,
row_number() over (partition by acct order by end_date desc) as seqnum
from t
) t
where seqnum = 1 and end_date < '2021-06-30'
union all
select acct, amt, dateadd(month, 1, begin_date),
eomonth(dateadd(month, 1, begin_date))
from cte
where begin_date < '2021-06-01'
)
select *
from cte;
然后您可以使用 insert
将这些行插入 table。或者,如果您只想要包含所有行的结果集,请使用 union all
。
Here 是一个 db<>fiddle.