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
。如果对于特定的 ID
,Value
不存在于任何 table 中,我将假设它是 'N'。假设对于特定的 ID
,值在 TabB 和 TabC 中,我想取 Value
,其中 LastUpdated
更大。
我试过使用循环,但这不是很有效的解决方案。我只需要结果游标中的 Key
和 Value
,并希望为此保留一个查询。
有人可以帮助确定比使用循环更好的解决方案吗?
编辑-
这是一个示例:
假设 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
)
)
)
如果 ID
在 TabB
和 TabC
中具有相同的 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
我有 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
。如果对于特定的 ID
,Value
不存在于任何 table 中,我将假设它是 'N'。假设对于特定的 ID
,值在 TabB 和 TabC 中,我想取 Value
,其中 LastUpdated
更大。
我试过使用循环,但这不是很有效的解决方案。我只需要结果游标中的 Key
和 Value
,并希望为此保留一个查询。
有人可以帮助确定比使用循环更好的解决方案吗?
编辑-
这是一个示例:
假设 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
)
)
)
如果 ID
在 TabB
和 TabC
中具有相同的 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