问题
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