涉及需要从行转换为列的日期的业务场景

时间:2014-11-05 14:50:48

标签: sql

我有以下要求。 我将数据存储在表格中,如下面的格式

ID  Region  State   Status           StatusDate
PCR1    1   GA      Initial          25-Oct-14
PCR1    1   GA      DM Review        27-Oct-14
PCR1    1   GA      SD Review        29-Oct-14
PCR1    1   GA      Final Review     31-Oct-14
PCR2    1   LA      Initial          25-Sep-14
PCR2    1   LA      DM Review        27-Sep-14
PCR2    1   LA      SD Review        29-Sep-14
PCR2    1   LA      Final Review     30-Sep-14

我想将上述数据转换为如下转换

ID  Region  State   Status         StartDate    EndDate
PCR1    1   GA      Initial        25-Oct-14    27-Oct-14
PCR1    1   GA      DM Review      27-Oct-14    29-Oct-14
PCR1    1   GA      SD Review      29-Oct-14    31-Oct-14
PCR1    1   GA      Final Review   31-Oct-14    Current Date
PCR2    1   LA      Initial        25-Sep-14    27-Sep-14
PCR2    1   LA      DM Review      27-Sep-14    29-Sep-14
PCR2    1   LA      SD Review      29-Sep-14    30-Sep-14
PCR2    1   LA      Final Review   30-Sep-14    Current Date

如何实现这一目标。 EnDate根据下一个状态的状态数据到达。对于最终状态,结束日期为当前系统日期。请注意,上面显示的状态是指示性的,可能会有所不同。提前感谢您的回复

此致 阿尼尔

1 个答案:

答案 0 :(得分:-1)

在任何支持窗口函数的dbms中,你可以非常简单地得到非常接近的东西。我在PostgreSQL中对此进行了测试,但它是标准的SQL,它也将在当前版本的SQL Server和Oracle中运行。 (对INSERT语句进行了微不足道的修改。)

create table test
  (id char(4) not null, 
   region int not null, 
   state char(2) not null, 
   status varchar(15) not null, 
   statusdate date not null,
   primary key (id, region, state, status)
);

insert into test values
('PCR1', 1, 'GA', 'Initial', '25-Oct-14'),
('PCR1', 1, 'GA', 'DM Review', '27-Oct-14'),
('PCR1', 1, 'GA', 'SD Review', '29-Oct-14'),
('PCR1', 1, 'GA', 'Final Review', '31-Oct-14'),
('PCR2', 1, 'LA', 'Initial', '25-Sep-14'),
('PCR2', 1, 'LA', 'DM Review', '27-Sep-14'),
('PCR2', 1, 'LA', 'SD Review', '29-Sep-14'),
('PCR2', 1, 'LA', 'Final Review', '30-Sep-14');

select id, region, state, status, statusdate,
lead(statusdate) over (partition by id order by statusdate) enddate
from test;
id    region  state  status        statusdate    enddate
--
PCR1  1       GA     Initial       2014-10-25    2014-10-27
PCR1  1       GA     DM Review     2014-10-27    2014-10-29
PCR1  1       GA     SD Review     2014-10-29    2014-10-31
PCR1  1       GA     Final Review  2014-10-31    
PCR2  1       LA     Initial       2014-09-25    2014-09-27
PCR2  1       LA     DM Review     2014-09-27    2014-09-29
PCR2  1       LA     SD Review     2014-09-29    2014-09-30
PCR2  1       LA     Final Review  2014-09-30    

你可以在输出中得到文字值'当前日期'而不是NULL,但如果我是你,我会认真思考。恕我直言,在应用程序代码中处理得更好。但是你可以这样重写SQL。

select id, region, state, status, statusdate, 
       coalesce(cast(enddate as varchar), 'Current date') enddate
from (select id, region, state, status, statusdate,
      lead(statusdate) over (partition by id order by statusdate) enddate
      from test
     ) x
id    region  state  status        statusdate    enddate
--
PCR1  1       GA     Initial       2014-10-25    2014-10-27
PCR1  1       GA     DM Review     2014-10-27    2014-10-29
PCR1  1       GA     SD Review     2014-10-29    2014-10-31
PCR1  1       GA     Final Review  2014-10-31    Current date
PCR2  1       LA     Initial       2014-09-25    2014-09-27
PCR2  1       LA     DM Review     2014-09-27    2014-09-29
PCR2  1       LA     SD Review     2014-09-29    2014-09-30
PCR2  1       LA     Final Review  2014-09-30    Current date

我更喜欢这种输出的应用程序代码,因为在SQL中,“enddate”列不能作为日期列返回。它必须作为varchar列返回。