组SQL的滞后函数

时间:2015-12-10 21:12:41

标签: sql sql-server

这就是我的表格。

    PID JNo EV Phase    Name
    100 1   1   NULL    Test1
    101 2   2   NULL    Test2
    102 3   3   NULL    Test3
    103 4   4   1       Test4.1
    103 4   4   1       Test4.2
    103 4   4   1       Test4.3
    104 5   5   3       Test5.1
    104 5   5   3       Test5.2
    104 5   5   3       Test5.3
    105 6   6   3       Test6.1
    105 6   6   3       Test6.2
    105 6   6   3       Test6.3
    107 7   7   NULL    Test7.1
    107 7   7   NULL    Test7.2
    107 7   7   NULL    Test7.3

我必须创建一个列,说明我的阶段是否已更改或基线。

例如:

  • 对于PID=100,第一阶段为空,因此应该是Baselined。
  • 对于PID=101阶段为空。之前的值(100)它是null,所以它应该基线为101.类似于102,它应该为null。
  • 对于PID=103阶段= 1.前一个值为(102)它为空。所以它应该是PhaseChange。
  • 对于PID=104阶段= 3.前一个值是(103)它是1所以它应该是PhaseChange。
  • 对于PID=105阶段= 3.之前的值是(104)它是3.所以它应该是Baselined。

示例数据:

PID JNo Ev  Phase   Name    PCH
100 1   1   NULL    Test1   Baselined
101 2   2   NULL    Test2   Baselined
102 3   3   NULL    Test3   Baselined
103 4   4   1       Test4.1 PhaseChange
103 4   4   1       Test4.2 PhaseChange
103 4   4   1       Test4.3 PhaseChange
104 5   5   3       Test5.1 PhaseChange
104 5   5   3       Test5.2 PhaseChange
104 5   5   3       Test5.3 PhaseChange
105 6   6   3       Test6.1 Baselined
105 6   6   3       Test6.2 Baselined
105 6   6   3       Test6.3 Baselined
107 7   7   NULL    Test7.1 PhaseChange
107 7   7   NULL    Test7.2 PhaseChange
107 7   7   NULL    Test7.3 PhaseChange

代码示例:

create Table #SampleTable
(ProjectID int,
JustNo int,
ERev int,
Phase int,
Name varchar(100) )

insert into #SampleTable values(100,1,1,Null,'Test1') 
insert into #SampleTable values(101,2,2,Null,'Test2')   
insert into #SampleTable values(102,3,3,Null,'Test3')   
insert into #SampleTable values(103,4,4,1,'Test4.1')   
insert into #SampleTable values(103,4,4,1,'Test4.2')   
insert into #SampleTable values(103,4,4,1,'Test4.3')   

insert into #SampleTable values(104,5,5,3,'Test5.1')   
insert into #SampleTable values(104,5,5,3,'Test5.2')   
insert into #SampleTable values(104,5,5,3,'Test5.3')   
insert into #SampleTable values(105,6,6,3,'Test6.1')   
insert into #SampleTable values(105,6,6,3,'Test6.2')   
insert into #SampleTable values(105,6,6,3,'Test6.3')   
insert into #SampleTable values(107,7,7,null,'Test7.1')   
insert into #SampleTable values(107,7,7,null,'Test7.2')   
insert into #SampleTable values(107,7,7,null,'Test7.3')   

select * from #SampleTable

我尝试使用Lag功能没有运气:(

2 个答案:

答案 0 :(得分:2)

您需要子查询来计算以前的状态并分配唯一的row_number。然后使用DENSE_RANK()将相同的ID分配给每个组。

<强> SQL Fiddle Demo

WITH phases as (
  SELECT DISTINCT 
         ProjectID,
         Phase,
         DENSE_RANK() over (ORDER BY ProjectID) as rn      
  FROM SampleTable
), table_rank as (
  SELECT *,
         DENSE_RANK() over (ORDER BY ProjectID) as rn           
  FROM SampleTable
)
SELECT t.*, p.*,
       CASE WHEN p.Phase IS NULL AND t.Phase IS NULL THEN 'Baselined'
            WHEN p.Phase = t.Phase THEN 'Baselined'
            ELSE 'PhaseChange'
       END PCH
FROM table_rank t
LEFT JOIN  phases p
       ON t.rn = p.rn + 1

<强>输出

我添加了额外的列,以便您可以调试结果。

/ --            table_rank                       -- / --          phase_rn      --/
| ProjectID | JustNo | ERev |  Phase |    Name | rn | ProjectID |  Phase |     rn |         PCH |
|-----------|--------|------|--------|---------|----|-----------|--------|--------|-------------|
|       100 |      1 |    1 | (null) |   Test1 |  1 |    (null) | (null) | (null) |   Baselined |
|       101 |      2 |    2 | (null) |   Test2 |  2 |       100 | (null) |      1 |   Baselined |
|       102 |      3 |    3 | (null) |   Test3 |  3 |       101 | (null) |      2 |   Baselined |
|       103 |      4 |    4 |      1 | Test4.1 |  4 |       102 | (null) |      3 | PhaseChange |
|       103 |      4 |    4 |      1 | Test4.2 |  4 |       102 | (null) |      3 | PhaseChange |
|       103 |      4 |    4 |      1 | Test4.3 |  4 |       102 | (null) |      3 | PhaseChange |
|       104 |      5 |    5 |      3 | Test5.1 |  5 |       103 |      1 |      4 | PhaseChange |
|       104 |      5 |    5 |      3 | Test5.2 |  5 |       103 |      1 |      4 | PhaseChange |
|       104 |      5 |    5 |      3 | Test5.3 |  5 |       103 |      1 |      4 | PhaseChange |
|       105 |      6 |    6 |      3 | Test6.1 |  6 |       104 |      3 |      5 |   Baselined |
|       105 |      6 |    6 |      3 | Test6.2 |  6 |       104 |      3 |      5 |   Baselined |
|       105 |      6 |    6 |      3 | Test6.3 |  6 |       104 |      3 |      5 |   Baselined |
|       107 |      7 |    7 | (null) | Test7.1 |  7 |       105 |      3 |      6 | PhaseChange |
|       107 |      7 |    7 | (null) | Test7.2 |  7 |       105 |      3 |      6 | PhaseChange |
|       107 |      7 |    7 | (null) | Test7.3 |  7 |       105 |      3 |      6 | PhaseChange |

答案 1 :(得分:0)

下面。要牢记两件事。初始加载将显示为phasechanged,因为之前没有比较。此外,当phase为null时,必须将其替换为与前一个值进行比较的值(反之亦然),因此我使用了isnull并用-1替换了null。理想情况下,它们不会为null或确保使用不能正常使用的值替换null。

DECLARE @SampleTable TABLE
(ProjectID int,
JustNo int,
ERev int,
Phase int,
Name varchar(100) )

insert into @SampleTable values(100,1,1,Null,'Test1'),(101,2,2,Null,'Test2'),(102,3,3,Null,'Test3'),(103,4,4,1,'Test4.1'),(103,4,4,1,'Test4.2'),(103,4,4,1,'Test4.3'),(104,5,5,3,'Test5.1'),(104,5,5,3,'Test5.2'),(104,5,5,3,'Test5.3'),(105,6,6,3,'Test6.1'),(105,6,6,3,'Test6.2'),(105,6,6,3,'Test6.3'),(107,7,7,null,'Test7.1'),(107,7,7,null,'Test7.2'),(107,7,7,null,'Test7.3')


select
    PROJECTID
    ,JUSTNO
    ,EREV
    ,PHASE
    ,NAME
    ,CASE LAG(ISNULL(PHASE,'-1')) OVER (ORDER BY PROJECTID, PHASE)
        WHEN ISNULL(PHASE,'-1') THEN 'BASELINED'
        ELSE 'PHASECHANGED'
        END AS PHC
from @SampleTable