创建虚拟行以将缺失值填充到 SQL 服务器 table
Create dummy rows to fill missing values into a SQL Server table
这个问题是我之前post的补充:
我有这个SQL服务器table;我想用截至上月末的虚拟数据填充 n 个缺失行,此时为 2021-06-30。我希望其他列 acct, type, amt
与 begin_date
和 end_date
相同,在 2021-06-30 之前增加 1 个月。
例如:acct 2 类型 B 在 2021-02-28 期间结束,因此我需要从该日期到上个月末(截至目前为 2021-06-)创建虚拟行30.
acct 2 type A
已经有到前几个月结束的行 2021-06-30
因此不需要虚拟行。
acct,type,amt, begin_date, end_date
1, C, 10, 2020-05-01, 2020-05-31
1, C, 10, 2020-06-01, 2020-06-30
2, B, 50 ,2021-01-01, 2021-01-31
2, B, 50 ,2021-02-01, 2021-02-28
2, A, 50 ,2021-05-01, 2021-05-31
2, A, 50 ,2021-06-01, 2021-06-30
这就是我想要的结果:
acct,type,amt, begin_date, end_date
1, C, 10, 2020-05-01, 2020-05-31
1, C, 10, 2020-06-01, 2020-06-30
....................................
1, C, 10, 2021-06-01, 2021-06-30
2, B, 50 ,2021-01-01, 2021-01-31
2, B, 50 ,2021-02-01, 2021-02-28
2, B, 50 ,2021-03-01, 2021-03-31
2, B, 50 ,2021-04-01, 2021-04-30
2, B, 50 ,2021-05-01, 2021-05-31
2, B, 50 ,2021-06-01, 2021-06-30
然后我就可以对原来的 table 或 union all
做一个 insert
Numbers table 除了评论,如果你的 table 包含某处(任何行)的所有日期,你可以通过一些交叉连接
来修补你的数据
SELECT * FROM
(SELECT DISTINCT begin_date, end_date FROM x) a
CROSS JOIN
SELECT DISTINCT acct, type, amt FROM x) b
如果不能依赖数据具有每个不同的日期,请创建一个 numbers/calendar table 并左连接到它
您的 SQL 服务器是否具有 EOMONTH
功能也值得一试;可以帮助您放弃结束日期
根据您的数据,1/C 在您指定的日期前一年结束。所以,它也应该生成行。
我看到了与您之前问题的不同之处:
- 你有
acct
/type
在一起。
- 截止日期根据当前日期动态变化。
所做的更改实际上只是对早期查询的微调:
with cte as (
select acct, type, 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, type order by end_date desc) as seqnum
from t
) t
where seqnum = 1 and end_date < eomonth(getdate(), -2)
union all
select acct, type, amt, dateadd(month, 1, begin_date),
eomonth(dateadd(month, 1, begin_date))
from cte
where begin_date < eomonth(getdate(), -2)
)
select *
from cte;
Here 是一个 db<>fiddle.
这个问题是我之前post的补充:
我有这个SQL服务器table;我想用截至上月末的虚拟数据填充 n 个缺失行,此时为 2021-06-30。我希望其他列 acct, type, amt
与 begin_date
和 end_date
相同,在 2021-06-30 之前增加 1 个月。
例如:acct 2 类型 B 在 2021-02-28 期间结束,因此我需要从该日期到上个月末(截至目前为 2021-06-)创建虚拟行30.
acct 2 type A
已经有到前几个月结束的行 2021-06-30
因此不需要虚拟行。
acct,type,amt, begin_date, end_date
1, C, 10, 2020-05-01, 2020-05-31
1, C, 10, 2020-06-01, 2020-06-30
2, B, 50 ,2021-01-01, 2021-01-31
2, B, 50 ,2021-02-01, 2021-02-28
2, A, 50 ,2021-05-01, 2021-05-31
2, A, 50 ,2021-06-01, 2021-06-30
这就是我想要的结果:
acct,type,amt, begin_date, end_date
1, C, 10, 2020-05-01, 2020-05-31
1, C, 10, 2020-06-01, 2020-06-30
....................................
1, C, 10, 2021-06-01, 2021-06-30
2, B, 50 ,2021-01-01, 2021-01-31
2, B, 50 ,2021-02-01, 2021-02-28
2, B, 50 ,2021-03-01, 2021-03-31
2, B, 50 ,2021-04-01, 2021-04-30
2, B, 50 ,2021-05-01, 2021-05-31
2, B, 50 ,2021-06-01, 2021-06-30
然后我就可以对原来的 table 或 union all
insert
Numbers table 除了评论,如果你的 table 包含某处(任何行)的所有日期,你可以通过一些交叉连接
来修补你的数据SELECT * FROM
(SELECT DISTINCT begin_date, end_date FROM x) a
CROSS JOIN
SELECT DISTINCT acct, type, amt FROM x) b
如果不能依赖数据具有每个不同的日期,请创建一个 numbers/calendar table 并左连接到它
您的 SQL 服务器是否具有 EOMONTH
功能也值得一试;可以帮助您放弃结束日期
根据您的数据,1/C 在您指定的日期前一年结束。所以,它也应该生成行。
我看到了与您之前问题的不同之处:
- 你有
acct
/type
在一起。 - 截止日期根据当前日期动态变化。
所做的更改实际上只是对早期查询的微调:
with cte as (
select acct, type, 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, type order by end_date desc) as seqnum
from t
) t
where seqnum = 1 and end_date < eomonth(getdate(), -2)
union all
select acct, type, amt, dateadd(month, 1, begin_date),
eomonth(dateadd(month, 1, begin_date))
from cte
where begin_date < eomonth(getdate(), -2)
)
select *
from cte;
Here 是一个 db<>fiddle.