Oracle/Sybase SQL - get value based on a previous record (not a simple LAG)

半世苍凉 提交于 2019-12-11 02:05:31

问题


I have data that is organized as follows:

Invoice_Id  Invoice_Line  Kit_Flag  Part_Number
----------  ------------  --------  -----------
AB12345               1    K        KT-1234A
AB12345               2    C        1234567
AB12345               3    C        1234568
AB12345               4    C        1234569
AB12345               5    C        1234560
AB12345               6    K        KT-1234C
AB12345               7    C        1234561
AB12345               8    C        1234562
AB12345               9    K        KT-1234Q
AB12345              10    C        5678901
AB12345              11    C        1234561
AB12345              12    C        1234562

I am attempting to get the Part_Number value for subsequent lines from the last line where the Kit_Flag was a 'K,' within a single Invoice_Id (K = Parent, C = Child). I only listed one invoice ID here for simplicity.

So, for the data above, the results would look like this:

Invoice_Id  Invoice_Line  Kit_Flag  Part_Number Parent_Part
----------  ------------  --------  ----------- ------------
AB12345               1    K        KT-1234A    KT-1234A
AB12345               2    C        1234567     KT-1234A
AB12345               3    C        1234568     KT-1234A
AB12345               4    C        1234569     KT-1234A
AB12345               5    C        1234560     KT-1234A
AB12345               6    K        KT-1234C    KT-1234C
AB12345               7    C        1234561     KT-1234C
AB12345               8    C        1234562     KT-1234C
AB12345               9    K        KT-1234Q    KT-1234Q
AB12345              10    C        5678901     KT-1234Q
AB12345              11    C        1234561     KT-1234Q
AB12345              12    C        1234562     KT-1234Q

In Excel, this is possible by something like "=If(C2="K",C3,D2)," and that's actually what we had to settle with for the time being, but I am trying to automate this.

The table is on both Oracle 9i and Sybase, but the Sybase instance does not have analytic functions.

I didn't think this would work (and it didn't), but notionally it shows what I am trying to do:

select
  t.Invoice_Id, t.Invoice_Line, t.Kit_Flag, t.Part_Number,
  case
    when Kit_Flag = 'K' then Part_Number
    else lag(Parent_Part, 1) over (partition by Invoice_Id order by Invoice_Line)
  end as Parent_Part
from Invoice_Data t

Any advice and/or guidance is welcome.


回答1:


One way to do this is with nested ranking functions. First, assign a constant value to everything that gets one value (using max() over) and then use this as a partition.

select t.Invoice_Id, t.Invoice_Line, t.Kit_Flag, t.Part_Number,
       max(KitPart) over (partition by invoice_id, KitNum) as Parent_Part
from (select t.*,
             sum(isKit) over (partition by InvoiceId order by InvoiceLine) as KitNum
      from (select t.Invoice_Id, t.Invoice_Line, t.Kit_Flag, t.Part_Number,
                   (case when Kit_Flag = 'K' then 1 else 0 end) as IsKit,
                   (case when Kit_Flag = 'K' then Part_Number end) as KitPart
            from Invoice_Data t
           ) t
     ) t


来源:https://stackoverflow.com/questions/13849192/oracle-sybase-sql-get-value-based-on-a-previous-record-not-a-simple-lag

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!