Oracle SQL: 从多个表中提取数据

Oracle SQL: Extracting data from multiple tables

我有 3 个 table,比如 TabA、TabB 和 TabC。以下是这些 table 中的一些有用的列:

TabA(ID VARCHAR2 Primary Key, ..)

TabB(ID VARCHAR2, Value CHAR(1), LastUpdated Date)

TabC(ID VARCHAR2 Primary Key, Value CHAR(1), LastUpdated Date)

这里Value是一个标志'Y'或'N'。我想使用这 3 个 table 获取所有 ID 及其 Value。首先,我想查看所有 table 中存在的所有不同的 ID。由于 Value 不在 TabA 中,我将只在 TabB 和 TabC 中查找 Value。如果对于特定的 IDValue 不存在于任何 table 中,我将假设它是 'N'。假设对于特定的 ID,值在 TabB 和 TabC 中,我想取 Value,其中 LastUpdated 更大。

我试过使用循环,但这不是很有效的解决方案。我只需要结果游标中的 KeyValue,并希望为此保留一个查询。

有人可以帮助确定比使用循环更好的解决方案吗?

编辑-

这是一个示例:

假设 TabA 是 -

ID
100
101
102

TabB 是 -

ID Value LastUpdated
99 Y 21-May-22
100 N 22-May-22
103 N 23-May-22

TabC 是 -

ID Value LastUpdated
102 Y 20-May-22
103 Y 24-May-22
104 N 21-May-22

结果应该是-

ID Value Why?
99 Y from TabB
100 N from TabB
101 N In TabA only so defaulting N
102 Y from TabC
103 Y In TabB and TabC but LastUpdated is greater in TabC so taking TabC value
104 N from TabC

编辑-

如果 ID 在 TabB 和 TabC 中具有相同的 LastUpdated 但具有不同的值,则预期结果 - 这可以忽略,因为这种情况很少见。我们可以假设这永远不会发生。

使用UNION从多个表创建一个数据集。然后,对该数据集进行过滤。

SELECT ID, Value
FROM
(
    SELECT ID, Value, MAX(LastUpdated) AS LastUpdated
    FROM TabB
    GROUP BY ID, Value
    UNION ALL
    SELECT ID, Value, MAX(LastUpdated) AS LastUpdated
    FROM TabC
    GROUP BY ID, Value
) t
WHERE ID IN
(
    SELECT DISTINCT ID
    FROM TabA
)
AND
(
    Value = 'Y' OR
    NOT EXISTS
    (
        SELECT 1
        FROM
        (
            SELECT ID, Value
            FROM
            (
                SELECT ID, Value, MAX(LastUpdated) AS LastUpdated
                FROM TabB
                GROUP BY ID, Value
                UNION ALL
                SELECT ID, Value, MAX(LastUpdated) AS LastUpdated
                FROM TabC
                GROUP BY ID, Value
            ) t
            WHERE ID = t.ID
        )
    )
)

如果 IDTabBTabC 中具有相同的 LastUpdated 但不同的 Value,请定义预期结果。在下面它是未定义的。

WITH BC AS (
    SELECT ID, VALUE FROM (
        SELECT ID, VALUE, 
        ROW_NUMBER() OVER (PARTITION BY ID ORDER BY LastUpdated DESC) r
        FROM (
            SELECT ID, Value, MAX(LastUpdated) AS LastUpdated
            FROM TabB
            GROUP BY ID, Value
            UNION ALL
            SELECT ID, Value, MAX(LastUpdated) AS LastUpdated
            FROM TabC
            GROUP BY ID, Value
        )
    )
    WHERE R = 1
)
SELECT ID, VALUE FROM BC
UNION ALL
SELECT ID, 'N' VALUE FROM tabA A
WHERE A.ID NOT IN (
    SELECT ID FROM BC
)
ORDER BY ID;

您可以尝试这样的操作:

SELECT id, value FROM
(SELECT id, value, ROW_NUMBER()
OVER (PARTITION BY id ORDER BY lastupdated DESC) AS rownr
FROM
(SELECT id, 'N' AS value, sysdate AS lastupdated FROM taba
WHERE id NOT IN (SELECT id FROM tabb) 
AND id NOT IN (SELECT id FROM tabc)
UNION
SELECT id, value, MAX(lastupdated) AS lastupdated
FROM tabb
GROUP BY id, value
UNION
SELECT id, value, MAX(lastupdated) AS lastupdated
FROM tabc
GROUP BY id, value
ORDER BY id, lastupdated DESC)) WHERE rownr = 1;

至少在我的 fiddle 示例中,这可以正常工作:db<>fiddle