如何将一系列记录转换为 SQL 中该范围之后的记录值?

Posted

技术标签:

【中文标题】如何将一系列记录转换为 SQL 中该范围之后的记录值?【英文标题】:How to transform a range of records to the values of the record after that range in SQL? 【发布时间】:2020-08-04 15:31:40 【问题描述】:

我正在尝试用正确的记录替换特定日期范围内的一些错误输入记录。但是,我不确定是否有有效的方法来做到这一点。因此,我的问题是如何将(静态)记录范围转换为 SQL 中该范围之后的记录值?您将在下面找到一个示例来阐明我试图实现的目标。

在此示例中,您可以看到客户编号 1 在 2020 年 6 月 25 日至 2020 年 6 月 29 日期间属于组编号 0(无)。从 30-06-2020 到 05-07-2020,对于客户编号 1,此组编号从 0 更改为 11。此静态期间包含错误的记录,应更改为 2020 年 6 月 7 日有效的值(组号 == 10)。有没有办法做到这一点?

【问题讨论】:

【参考方案1】:

如果我理解正确,您可以使用窗口函数来获取该特定日期的数据,并使用case 逻辑将其分配给特定日期范围:

select t.*,
       (case when date >= '2020-07-01' and date <= '2020-07-05'
             then max(case when date = '2020-07-06' then group_number end) over (partition by customer_number)
             else group_number
        end) as imputed_group_number,
       (case when date >= '2020-07-01' and date <= '2020-07-05'
             then max(case when date = '2020-07-06' then role end) over (partition by customer_number)
             else role
        end) as imputed_role
from t;

如果要更新值,可以使用JOIN

update t
    set group_number = tt.group_number,
        role = tt.role
    from tt
    where tt.customer_number = t.customer_number and tt.date = '2020-07-06'

【讨论】:

【参考方案2】:

我认为窗口函数 first_value() 可以满足您的需求:

select 
    date,
    customer_number,
    first_value(group_number) over(partition by customer_number order by date) group_number,
    first_value(role)         over(partition by customer_number order by date) role
from mytable

【讨论】:

这仅适用于第一个值对每条记录都有效的情况。但是,情况并非如此,因为值会随着时间而改变。因此,在这组错误记录之后,应将不良记录替换为第一个有效记录。具体来说,在这种情况下,29-06-2020 和 05-07-2020 之间的记录应替换为 06-07-2020 的记录。我用更多细节调整了这个例子。【参考方案3】:

您可以执行以下操作作为示例。在这里,我选择了如果 role='Leader' 记录不好的标准,因此您将在 group_number1 列和 role1 中应用下一个可用的 group_number -->。

我在你的 excel 示例中使用了一小部分行。

  select date1
        ,customer_number
        ,group_number
        ,case when role='Leader' then 
                  (select t1.group_number
                     from t t1
                    where t1.date1>t.date1
                      and t1.role<>'Leader'
                   order by t1.date1 asc
                   limit 1
                  ) 
             else group_number 
         end as group_number1
        ,role
       ,case when role='Leader' then 
                  (select t1.role
                     from t t1
                    where t1.date1>t.date1
                      and t1.role<>'Leader'
                   order by t1.date1 asc
                   limit 1
                  ) 
             else role 
         end as role1
   from t
order by 1   

+------------+-----------------+--------------+---------------+--------+--------+
|   DATE1    | CUSTOMER_NUMBER | GROUP_NUMBER | GROUP_NUMBER1 |  ROLE  | ROLE1  |
+------------+-----------------+--------------+---------------+--------+--------+
| 2020-06-25 |               1 |            0 |             0 | None   | None   |
| 2020-06-26 |               1 |            0 |             0 | None   | None   |
| 2020-06-27 |               1 |            0 |             0 | None   | None   |
| 2020-06-28 |               1 |            0 |             0 | None   | None   |
| 2020-06-29 |               1 |            0 |             0 | None   | None   |
| 2020-06-30 |               1 |           11 |            10 | Leader | Member |
| 2020-07-01 |               1 |           11 |            10 | Leader | Member |
| 2020-07-06 |               1 |           10 |            10 | Member | Member |
+------------+-----------------+--------------+---------------+--------+--------+

db 小提琴链接 https://dbfiddle.uk/?rdbms=db2_11.1&fiddle=c95d12ced067c1df94947848b5a94c14

【讨论】:

以上是关于如何将一系列记录转换为 SQL 中该范围之后的记录值?的主要内容,如果未能解决你的问题,请参考以下文章

使用 SQL JOIN,如何将一张表的结果限制为最近的记录

sql语句,怎么将一段日期分割成每日?请高人解答。

sql怎么将一系列点经纬度坐标匹配到某市

Oracle通过一个字段的值将一条记录拆分为多条记录

AWS Firehose 到 Elastic Search - 将一条 Firehose 记录转换为多个 Elastic 条目

如何以编程方式将 HQL 转换为 SQL 查询(不记录)