我在Oracle,INVOICES和HOLDS中有两个表,我使用invoice_id连接。并非所有发票都有效,但有些发票会有多个保留事件。我想只选择一个发票并解码release_status字段。 如果有多个保持事件,我需要分析它是否已被释放。如果一行没有释放代码,则仍然保留整个发票。 示例表:
Invoice_num |Hold_Reason |Release_Lookup_code
10001 |Inv Hold |Quick release
10002 |Inv Hold |Quick release
10003 |Inv Hold |(NULL)
10004 |Inv Hold |Quick release
10004 |Inv Hold |Quick release
10004 |Amt Hold |(NULL)
10005 |Inv Hold |Variance Corrected
10005 |Inv Hold |Quick release
10006 | (NULL) |(NULL)
我想要显示的结果:
Invoice num |Hold Reason |Hold Status
10001 |Inv Hold |Released
10002 |Inv Hold |Released
10003 |Inv Hold |Held
10004 |Inv Hold |Held
10005 |Inv Hold |Released
10006 |(NULL) |Not Held
目前我只有这个代码,它会带回多行:
select
inv.invoice_num,
hold.hold_reason,
(CASE WHEN hold.invoice_id is not null
then (CASE WHEN HOLD.RELEASE_LOOKUP_CODE is null then 'HELD' else 'RELEASED' END)
else 'NOT HELD' END) Hold_Status
from AP.AP_INVOICES_ALL INV,
AP.AP_HOLDS_ALL HOLD
WHERE inv.invoice_id = hold.invoice_id (+)
order by 1
我想过计算发票的数量,但之后我仍然需要分析Release_Lookup_Code字段的内容。 我不是在寻找完整的答案,只是关于我应该如何进行的一些建议。
答案 0 :(得分:2)
像这样的东西。在发票保留表上进行复制。
with AP_HOLDS_ALL(invoice_id, Hold_Reason, Release_Lookup_code) as
(select 10001, 'Inv Hold', 'Quick release' from dual
union all
select 10002, 'Inv Hold', 'Quick release' from dual
union all
select 10003, 'Inv Hold', '' from dual
union all
select 10004, 'Inv Hold', 'Quick release' from dual
union all
select 10004, 'Inv Hold', 'Quick release' from dual
union all
select 10004, 'Amt Hold', '' from dual
union all
select 10005, 'Inv Hold', 'Variance Corrected' from dual
union all
select 10005, 'Inv Hold', 'Quick release' from dual
union all
select 10006, '', '' from dual)
, AP_HOLDS_ALL_deplicated as
(select s.*
, row_number()
over(partition by invoice_id
order by decode(Release_Lookup_code, 'Quick release', 1, 'Variance Corrected', 2, 3) desc)
rn
from AP_HOLDS_ALL s)
, AP_INVOICES_ALL(invoice_id) as
(select 10001 from dual
union all
select 10002 from dual
union all
select 10003 from dual
union all
select 10004 from dual
union all
select 10005 from dual
union all
select 10006 from dual)
select --inv.invoice_num,
inv.invoice_id
, hold.hold_reason
, (case
when hold.invoice_id is not null then
(case
when HOLD.RELEASE_LOOKUP_CODE is null then 'HELD'
else 'RELEASED'
end)
else
'NOT HELD'
end)
Hold_Status
from AP.AP_INVOICES_ALL INV, AP.AP_HOLDS_ALL_deplicated HOLD
where inv.invoice_id = hold.invoice_id(+) and HOLD.rn = 1
order by 1
答案 1 :(得分:2)
与@ Arkadiusz的答案类似的想法,但使用keep ... dense_rank
而不是明确的步骤来查找行号:
-- CTEs to provide your sample data
with ap_invoices_all (invoice_id) as (
select 10001 from dual
union all select 10002 from dual
union all select 10003 from dual
union all select 10004 from dual
union all select 10005 from dual
union all select 10006 from dual
),
ap_holds_all (invoice_id, hold_reason, release_lookup_code) as (
select 10001, 'Inv Hold', , 'Quick release' from dual
union all select 10002, 'Inv Hold', 'Quick release' from dual
union all select 10003, 'Inv Hold', null from dual
union all select 10004, 'Inv Hold', 'Quick release' from dual
union all select 10004, 'Inv Hold', 'Quick release' from dual
union all select 10004, 'Amt Hold', null from dual
union all select 10005, 'Inv Hold', 'Variance Corrected' from dual
union all select 10005, 'Inv Hold', 'Quick release' from dual
union all select 10006, null, null from dual
)
-- end of CTEs for sample data
select
inv.invoice_id,
max(hold.hold_reason) keep (dense_rank last order by case
when hold.release_lookup_code is null then 1 else 0
end) as hold_reason,
case
when max(hold.hold_reason) is null then 'NOT HELD'
when max(hold.release_lookup_code)
keep (dense_rank last order by case
when hold.release_lookup_code is null then 1 else 0
end) is not null then 'RELEASED'
else 'HELD'
end as hold_status
from ap_invoices_all inv
left join ap_holds_all hold
on hold.invoice_id = inv.invoice_id
group by inv.invoice_id
order by 1;
得到:
INVOICE_ID HOLD_REA HOLD_STA
---------- -------- --------
10001 Inv Hold RELEASED
10002 Inv Hold RELEASED
10003 Inv Hold HELD
10004 Amt Hold HELD
10005 Inv Hold RELEASED
10006 NOT HELD
排名是优先保留具有空释放代码的保留记录,既可以找到适当的保留原因,也可以决定是否存在任何未结保留 - 确定是否保留或释放。
对于这个版本,如果您有一个发票的两个未结保留,那么您只会看到它报告一次,即使保留原因不同(例如,如果您同时保持amt和inv保持打开10004)。如果你想看到两者,那么你可以按两个字段进行分组,这将略微简化查询的其余部分;但是你也会因为这两个原因而看到释放。如果存在偏好,您还可以优先考虑在该场景中看到哪种持有原因。