创建虚拟行以将缺失值填充到 SQL 服务器 table

Create dummy rows to fill missing values into a SQL Server table

这个问题是我之前post的补充:

我有这个SQL服务器table;我想用截至上月末的虚拟数据填充 n 个缺失行,此时为 2021-06-30。我希望其他列 acct, type, amtbegin_dateend_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.