识别历史表中状态已更改两次的 SKU id

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

我有一个历史表,其中包含 id、日期和状态列。我试图识别 id 从状态 1(活动)更改为 0(非活动)并返回到 1(再次活动)的所有实例。我想创建一个数据透视表,其中所有不同的 id 作为行,所有日期作为列值。因为这是一个历史表,并且有大约 10M 个不同的 id,所以我试图看看什么是提取数据的理想/有效方法。

数据如下:

id       date       status
I01234   5/12/2023  1
I14690   4/13/2021  0

最终数据结构:

id      01/01/2021 01/02/2021 01/03/2021 ........ 10/31/2023
I01234  1          1          1                   0
I14690  1          0          0                   1
sql sql-server pivot-table
1个回答
0
投票

这将获取每个 id 从 active->inactive->active 移动的所有记录。请注意,这将拾取在任何时候具有此生命周期的记录,无论其当前状态如何。

还假设数据透视表不是必需的,我们只需要 ids/记录。

inactive_sandwich 子句中有两个主要条件。

第一个检查(通过 EXISTS)是否有该 id 的活动状态早于非活动状态的记录。

第二个是相同的想法,但检查活动记录晚于非活动记录的加载日期。

如果这两者都为真,则意味着您有一个较早的“活动”、一个“非活动”和一个较晚的“活动”。

此结果只会为您提供非活动记录,因此最后一个子句将选取与这些 id 关联的所有记录。

create table some_test_data 
  ( id varchar(100),
    status integer,
    load_date date
  )

insert into some_test_data values ('abc',1,cast('2023-01-01' as datetime));
insert into some_test_data values ('abc',0,cast('2023-01-02' as datetime));
insert into some_test_data values ('abc',1,cast('2023-01-03' as datetime));
insert into some_test_data values ('cde',1,cast('2023-01-04' as datetime));
insert into some_test_data values ('cde',1,cast('2023-01-05' as datetime));
insert into some_test_data values ('efg',1,cast('2023-01-05' as datetime));
insert into some_test_data values ('efg',0,cast('2023-01-05' as datetime));

with inactive_sandwich as (
    select *
      from some_test_data t1
     where t1.status = 0
       and exists
             ( select 1
                 from some_test_data earlier_active
                where t1.id = earlier_active.id
                  and t1.load_date > earlier_active.load_date
                  and earlier_active.status = 1                
             )
       and exists
             ( select 1
                 from some_test_data later_active
                where t1.id = later_active.id
                  and t1.load_date < later_active.load_date
                  and later_active.status = 1                
             )
)
select * 
  from some_test_data t1 
 where exists
         (
           select 1
             from inactive_sandwich t2
            where t1.id = t2.id

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