根据单个日期列计算具有 from_date 和 to_date 的一组行

问题描述 投票:0回答:1

我有一个 customer_audit 表,记录发生在客户表上的 INSERT 和 UPDATE。

客户审核

id 操作 时间戳 客户 ID 地址1 地址2
1 2024-10-05 100 链接st 1号
2 2024-10-06 100 链接st 2号
3 2024-10-07 100 连接路 2号
4 2024-10-08 100 连接路 数量200
5 2024-10-06 200 公园街 20号
6 2024-10-08 200 公园街 数量200

预期输出(在本例中为

address1
address2
)分别显示地址 1 和地址 2 的所有历史值,其中
from_date
to_date
根据时间戳列计算。

例如对于 customer_id 100:

客户 ID 列名称 列值 起始日期 截止日期
100 地址1 链接st 2024-10-05 2024-10-07
100 地址1 连接路 2024-10-07 null(表示列值是当前值)
100 地址2 1号 2024-10-05 2024-10-06
100 地址2 2号 2024-10-06 2024-10-08
100 地址2 数量200 2024-10-08

我通过稍微调整 mcwolf 的查询来解决这个问题:

select customer_id, name, 'address1' as attribute_name, address1 as "attribute_value", min(from_date) as "valid_from", max(to_date) as "valid_to"
from (
select customer_id, 
       name, 
       address1,
       "mod_timestamp" from_date,
         COALESCE(lead("mod_timestamp") over change_window, to_date('99991231', 'yyyymmdd')) to_date,
       ROW_NUMBER () OVER ( PARTITION BY customer_id, address1 ORDER BY mod_timestamp) as rownum
from customer_audit
WINDOW change_window as (PARTITION BY customer_id order by mod_timestamp)   
order by customer_id, mod_timestamp ) a
group by customer_id, name, attribute_name, "attribute_value"
order by customer_id, "valid_from";
sql postgresql
1个回答
0
投票

...这是另一种方法...

WITH
  dates AS    -- track changes of addresses ( ..._rn = 1 )
    ( Select ca.id, customer_id, "timestamp" as ts,
             address1, Row_Number() Over(Partition By customer_id, address1 Order By id) addr1_rn,
             address2, Row_Number() Over(Partition By customer_id, address2 Order By id) addr2_rn
      From   customer_audit ca
    ) 
--    M a i n    S Q L : 
SELECT  f.customer_id, 'address1' as column_name, f.address1 as column_value, f.ts as from_date,  
        Lead(ts) Over(Partition By customer_id, 'address1' Order By id) as to_date
FROM  ( Select  * From  dates Where addr1_rn = 1 ) f
UNION ALL 
SELECT  f.customer_id, 'address2', f.address2, f.ts, 
        Lead(ts) Over(Partition By customer_id, 'address2' Order By id) as to_date
FROM  ( Select  * From  dates Where addr2_rn = 1 ) f 
ORDER BY  customer_id, column_name, from_date
/*     R e s u l t : 
customer_id column_name column_value    from_date               to_date
----------- ----------- --------------  ----------------------  ----------------------
        100 address1    link st         2024-10-05 00:00:00     2024-10-07 00:00:00
        100 address1    link road       2024-10-07 00:00:00     null
        100 address2    number 1        2024-10-05 00:00:00     2024-10-06 00:00:00
        100 address2    number 2        2024-10-06 00:00:00     2024-10-08 00:00:00
        100 address2    number 200      2024-10-08 00:00:00     null
--
        200 address1    park st         2024-10-06 00:00:00     null
        200 address2    number 20       2024-10-06 00:00:00     2024-10-08 00:00:00
        200 address2    number 200      2024-10-08 00:00:00     null                    */

请参阅此处的小提琴

© www.soinside.com 2019 - 2024. All rights reserved.