【问题标题】:Create dummy rows to fill missing values into a SQL Server table创建虚拟行以将缺失值填充到 SQL Server 表中
【发布时间】:2021-07-11 19:56:42
【问题描述】:

这个问题是我之前的帖子的补充:Insert dummy rows to fill missing values into a SQL Table

我有这个 SQL Server 表;我想用上个月末的虚拟数据填充 n 行缺失的行,此时为 2021 年 6 月 30 日。我希望其他列 acct, type, amtbegin_dateend_date 相同,在 2021 年 6 月 30 日之前增加 1 个月。

例如:acct 2 type B 在 2021 年 2 月 28 日结束,因此我需要从该日期创建虚拟行,直到上个月月底,截至目前为 2021 年 6 月 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

然后我可以对原始表执行 insertunion all

【问题讨论】:

  • 这就是为什么你要有一个数字表

标签: sql-server stored-procedures sql-order-by common-table-expression recursive-query


【解决方案1】:

根据您的数据,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 是一个 dbfiddle。

【讨论】:

  • 感谢@GordonLinoff,您是一位真正的大师。我自己刚刚在我的解释中看到我没有以 2021-06-30 结束 1/C,然后你把它捡起来了。再次感谢您,您是数据整理方面的真正专家。
  • @GordonIinoff,我从小提琴结果中看到它生成到 2021-07-31 而不是 2021-06-30。我将在 where 子句中修改日期减法。
【解决方案2】:

撇开数字表注释不谈,如果您的表在某处(任何行)包含所有日期,您可以通过交叉连接来修补数据

SELECT * FROM
  (SELECT DISTINCT begin_date, end_date FROM x) a
  CROSS JOIN
  SELECT DISTINCT acct, type, amt FROM x) b

如果不能依赖数据来获得每个不同的日期,请创建一个数字/日历表并将其左连接

如果您的 SQL Server 具有 EOMONTH 函数,可能也值得一试;可以帮助你放弃结束日期

【讨论】:

    猜你喜欢
    • 2021-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-27
    • 2020-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多