Oracle 视图查询中添加 If-else 条件

问题描述 投票:0回答:1

我的oracle数据库有3张表

Order (id, order_number, external_id(FK to other app),version, description, create_tS) 
Partner (id, order_id(FK to orders),partner_code, partner_name, identifier, type, value)
Fees (id, order_id(FK to orders), identifier, type, value)

在合作伙伴表中,标识符将具有

(INTERNAL, EXTERNAL, LOCAL)
不同的值,类型将具有
(A,B,C,D,E)
不同的值,值列将具有其对应的值。因此,对于一个 order_id,它将有 5x3 15 行,每个标识符和类型。

类似地,在费用表中,标识符将具有(EXPENSE、BILLED、SETTLED)不同值,类型将具有(F1、F2、F3、F4)不同值,并且值列将具有其对应的值。每个 order_id 都有 3x4 12 行

基本上这些桌子是垂直的桌子,而不是水平的。

现在我创建了一个视图,其中所有这些水平表都进行水平转换,并且应该有一个唯一的行用于 order_number、external_id 和 Partner_code 的复合键,并且应该是具有最大版本的行。

order_data_view(order_number, external_id, partner_code, partner_name, version, create_ts, description, value_a, value_b, value_c, value_d, value_e, value_f1, value_f2, value_f3, value_f4)

SQL如下

CREATE OR REPLACE VIEW "order_data_view" (order_number, external_id, partner_code, version, partner_name, create_ts, description
value_a, value_b, value_c, value_d, value_e, value_f1, value_f2, value_f3, value_f4) AS
 select o.order_number, o.external_id, p.partner_code, o.version,
    MAX(p.partner_name) as partner_name,
    MAX(o.create_ts) AS create_ts,   
    MAX(o.description) as description,
    MAX(CASE WHEN p.identifier='INTERNAL' AND p.type='A' THEN p.value END) AS value_a,
    MAX(CASE WHEN p.identifier='INTERNAL' AND p.type='B' THEN p.value END) AS value_b,
    MAX(CASE WHEN p.identifier='EXTERNAL' AND p.type='C' THEN p.value END) AS value_c,
    MAX(CASE WHEN p.identifier='LOCAL' AND p.type='D' THEN p.value END) AS value_d,
    MAX(CASE WHEN p.identifier='LOCAL' AND p.type='E' THEN p.value END) AS value_e,
    MAX(CASE WHEN f.identifier='EXPENSE' AND f.type='F1' THEN f.value END) AS value_f1,
    MAX(CASE WHEN f.identifier='EXPENSE' AND f.type='F2' THEN f.value END) AS value_f2,
    MAX(CASE WHEN f.identifier='BILLED' AND f.type='F3' THEN f.value END) AS value_f3,
    MAX(CASE WHEN f.identifier='BILLED' AND f.type='F4' THEN f.value END) AS value_f4,
    from Order o
    LEFT JOIN Partner p ON o.id = p.order_id
    LEFT JOIN FEES f ON o.id = f.order_id
    where (o.order_number, o.external_id, o.version, o.create_ts) in (
        select o1.order_number, o1.external_id, MAX(o1.version), MAX(o1.create_ts) from Order o1 group by o1.order_number, o1.external_id)
    group by o.order_number, o.external_id, o.version, p.partner_code;

现在我需要添加另一张桌子。这也是立式桌子

order_attributes(id, order_number, external_id, partner_code, identifier, type, value)
该表将具有标识符
(CALCULATED, EDITED)
作为不同值,类型为
(X, Y, Z)
值,因此在所有 6 行中都有 order_number、external_id、partner_code

的复合键

现在我需要在我的视图中为 value_a、value_b(内部类型)和 value_f1、value_f2(费用类型)添加 if else 条件,这样,如果存在

value_a
的行,则
identifier=CALCULATED and type = X
将从“order_attributes”表中获取值。如果它不存在或者为空,那么它应该像以前一样从合作伙伴表中选择。
value_b
将会是
identifier=EDITED and type = X
或像以前一样。

以下是我对视图所做的更改。

CREATE OR REPLACE VIEW "order_data_view" (order_number, external_id, partner_code, version, partner_name, create_ts, description
value_a, value_b, value_c, value_d, value_e, value_f1, value_f2, value_f3, value_f4) AS
 select o.order_number, o.external_id, p.partner_code, o.version,
    MAX(p.partner_name) as partner_name,
    MAX(o.create_ts) AS create_ts,   
    MAX(o.description) as description,
    MAX(NVL(CASE WHEN a.identifier='CALCULATED' AND a.type='X' THEN a.value END,
        (CASE WHEN p.identifier='INTERNAL' AND p.type='A' THEN p.value END)) AS value_a,
    MAX(NVL(CASE WHEN a.identifier='EDITED' AND a.type='X' THEN a.value END,
        (CASE WHEN p.identifier='INTERNAL' AND p.type='B' THEN p.value END)) AS value_b,
    MAX(CASE WHEN p.identifier='EXTERNAL' AND p.type='C' THEN p.value END) AS value_c,
    MAX(CASE WHEN p.identifier='LOCAL' AND p.type='D' THEN p.value END) AS value_d,
    MAX(CASE WHEN p.identifier='LOCAL' AND p.type='E' THEN p.value END) AS value_e,
    MAX(CASE WHEN f.identifier='EXPENSE' AND f.type='F1' THEN f.value END) AS value_f1,
    MAX(CASE WHEN f.identifier='EXPENSE' AND f.type='F2' THEN f.value END) AS value_f2,
    MAX(CASE WHEN f.identifier='BILLED' AND f.type='F3' THEN f.value END) AS value_f3,
    MAX(CASE WHEN f.identifier='BILLED' AND f.type='F4' THEN f.value END) AS value_f4,
    from Order o
    LEFT JOIN Partner p ON o.id = p.order_id
    LEFT JOIN Fees f ON o.id = f.order_id
    LEFT JOIN order_attributes a ON o.order_number = a.order_number and o.external_id = a.external_id and p.partner_code = a.partner_code
    where (o.order_number, o.external_id, o.version, o.create_ts) in (
        select o1.order_number, o1.external_id, MAX(o1.version), MAX(o1.create_ts) from Order o1 group by o1.order_number, o1.external_id)
    group by o.order_number, o.external_id, o.version, p.partner_code;

问题就在于此。对于某些 order_number ,它工作正常,对于某些 order_number ,即使 order_attribute 列中有该匹配类型和标识符的值,某些列也是从合作伙伴表中选取的。就像 value_a 不会很好,但 value_b 会很好,并且在同一个查询中,如果有 2 个合作伙伴代码,在 4 个值中,3 个会很好,1 个是错误的。

我找不到问题所在。如果我在 else 情况下放置了错误的子句,有时效果很好

例如,如果以下代码为一个partner_code返回错误值

MAX(NVL(CASE WHEN a.identifier='CALCULATED' AND a.type='X' THEN a.value END,
          (CASE WHEN p.identifier='INTERNAL' AND p.type='A' THEN p.value END)) AS value_a,

将 else 情况更改为一些随机的东西即可使其工作

MAX(NVL(CASE WHEN a.identifier='CALCULATED' AND a.type='X' THEN a.value END,
          (CASE WHEN p.identifier='INTERNAL' AND p.type='ABC' THEN p.value END)) AS value_a,

我完全困惑了。请帮忙!!

sql oracle view case nvl
1个回答
0
投票

没有任何数据,也没有适当的可重现的情况,这只是猜测......但列“a.identifier”来自左连接的表。这通常意味着 PARTNER 中存在记录,而 ORDER_ATTRIBUTES 中没有匹配的行。对于这些行,“a.identifier”列的值将为 NULL。在 Oracle 中,NULL 不应与比较运算符一起使用,因为该结果是“UNKNOWN”(请参阅docs)。我建议通过使用 NVL(a.identifier,'XXX') 或在 case 语句中添加 IS NULL 子句来考虑 NULL 值的可能性。如果这个猜测不正确,那么我建议创建一个适当的可重现案例:表脚本、创建行的脚本、选择(它可能比您现在拥有的简单得多 - 只有返回错误结果的列才重要,您得到的输出和您期望的输出。

© www.soinside.com 2019 - 2024. All rights reserved.