【问题标题】:Insert dummy rows to fill missing values into a SQL Table插入虚拟行以将缺失值填充到 SQL 表中
【发布时间】:2021-09-20 11:49:04
【问题描述】:

我有这个 SQL Server 表 table1,我想在每个帐户中填充虚拟行,直到最近的上个月结束日期,例如现在最多 2021 年 6 月 30 日。

在此示例中,帐户 1 有 n 行,在 2020-05-31 结束,我想插入具有相同值的虚拟行 acctamt begin_dateend_date 递增到 2021 年 6 月 30 日为止的 1 个月。

假设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 年 5 月 31 日的最后一个时期到上个月末(现在是 2021 年 6 月 30 日)插入 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

基于一些数据分析,我意识到我需要另一个条件来解决问题。假设在table1 中添加了另一列type。所以accttype 将是标识每个相关行的复合键,因此acct 2 type A 和acct 2 type B 不相关。所以我们有了更新的表格:

 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

我现在需要在 2021 年 6 月 30 日之前为账户 2 类型 B 创建虚拟行。我们已经知道 acct 2 type A 是可以的,因为它已经有到 2021-06-30 的行

【问题讨论】:

  • 请阅读this,了解一些改进问题的技巧。 DDL 帮助我们帮助您,例如我们应该猜测“日期”是什么数据类型?你试过什么?

标签: sql-server tsql stored-procedures database-design user-defined-functions


【解决方案1】:

您可以使用递归 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 将这些行插入到表中。或者,如果您只是想要一个包含所有行的结果集,请使用 union all

Here 是一个 dbfiddle。

【讨论】:

  • 嗨@GordonLintoff,你能看到我更新的问题吗?根据一些数据分析,我需要对解决方案进行一些进一步的更改。
  • @JaxonX 。 . .在这种情况下提出一个新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-25
  • 2016-07-20
  • 2020-01-15
  • 2023-02-22
  • 1970-01-01
相关资源
最近更新 更多