我有
LEFT JOIN
ed 的三张桌子。在这种情况下,我需要使用 COALESCE(ID, ID1)
用 ID1 替换丢失的 ID。
目标是仅获取 ID 及其所有相关数据条目,给定 OPS 列中的值“w”。
我尝试使用
EXISTS
子句,但它只返回列 OPS 的值为 'w' 的行,而不返回与同一 ID 相关的其他行:
SELECT t1.id, t1.age, t2.operation, t3.ops
FROM table1 AS t1
LEFT JOIN table2 AS t2 ON COALESCE(t2.id, t2.id1) = t1.id
LEFT JOIN table3 AS t3 ON COALESCE(t3.id, t3.id1) = t1.id
WHERE EXISTS (SELECT 1
FROM table3
WHERE id = t1.id
AND (t3.ops = 'w'))
现在我试着弄清楚为什么我的
EXISTS
子句不能正常工作。
资料:
db<>小提琴
这是我想用代码产生的结果:
id | 年龄 | 操作 | 操作 |
---|---|---|---|
1 | 23 | A | q |
1 | 23 | A | w |
1 | 23 | A | e |
1 | 23 | 乙 | q |
1 | 23 | 乙 | w |
1 | 23 | 乙 | e |
1 | 23 | C | q |
1 | 23 | C | w |
1 | 23 | C | e |
2 | 25 | A | q |
2 | 25 | A | w |
2 | 25 | 乙 | q |
2 | 25 | 乙 | w |
4 | 43 | A | q |
4 | 43 | A | w |
4 | 43 | 乙 | q |
4 | 43 | 乙 | w |
如果我理解正确的话,我会推荐窗口函数而不是
exist
来检查每个组是否有操作w
:
SELECT *
FROM (
SELECT t1.id AS t1id,
t1.age AS t1age,
t2.id AS t2id,
t2.id1 AS t2id1,
t2.operation AS t2operation,
t3.id AS t3id,
t3.id1 AS t3id1,
t3.ops AS t3ops,
MAX(CASE WHEN t3.ops = 'w' then 1 else 0 end) OVER(PARTITION BY t1.id) has_ops_w
FROM table1 AS t1
LEFT JOIN table2 AS t2 ON COALESCE(t2.id, t2.id1) = t1.id
LEFT JOIN table3 AS t3 ON COALESCE(t3.id, t3.id1) = t1.id
) t
WHERE has_ops_w = 1
t1id | t1age | t2id | t2id1 | t2操作 | t3id | t3id1 | t3ops | has_ops_w |
---|---|---|---|---|---|---|---|---|
1 | 23 | 1 | 1 | A | 1 | 1 | q | 1 |
1 | 23 | 1 | 1 | A | 空 | 1 | w | 1 |
1 | 23 | 1 | 1 | A | 空 | 1 | e | 1 |
1 | 23 | 空 | 1 | 乙 | 1 | 1 | q | 1 |
1 | 23 | 空 | 1 | 乙 | 空 | 1 | w | 1 |
1 | 23 | 空 | 1 | 乙 | 空 | 1 | e | 1 |
1 | 23 | 空 | 1 | C | 1 | 1 | q | 1 |
1 | 23 | 空 | 1 | C | 空 | 1 | w | 1 |
1 | 23 | 空 | 1 | C | 空 | 1 | e | 1 |
2 | 25 | 2 | 2 | A | 2 | 2 | q | 1 |
2 | 25 | 2 | 2 | A | 空 | 2 | w | 1 |
2 | 25 | 2 | 2 | 乙 | 2 | 2 | q | 1 |
2 | 25 | 2 | 2 | 乙 | 空 | 2 | w | 1 |
4 | 43 | 4 | 4 | A | 4 | 4 | q | 1 |
4 | 43 | 4 | 4 | A | 空 | 4 | w | 1 |
4 | 43 | 空 | 4 | 乙 | 4 | 4 | q | 1 |
4 | 43 | 空 | 4 | 乙 | 空 | 4 | w | 1 |
GMB 指定的窗口函数可以工作,但是,我认为使用 EXISTS 子句有些混乱。
SELECT t1.id, t1.age, t2.operation, t3.ops
FROM table1 AS t1
LEFT JOIN table2 AS t2
ON COALESCE(t2.id, t2.id1) = t1.id
LEFT JOIN table3 AS t3 ON COALESCE(t3.id, t3.id1) = t1.id
WHERE EXISTS (
SELECT 1
FROM table3 inner_t3
WHERE COALESCE(inner_t3.id, inner_t3.id1) = t1.id -- your join above wasn't
-- on ID alone. This one
-- shouldn't be either
AND inner_t3.ops = 'w' -- Make sure you have proper reference to inner
-- table using alias.
)
行得通。那么是不是因为从 ID1 替换 ID 的 CLAUSE 需要在 exists 子句中再次重复?
SELECT t1.id, t1.age, t2.operation, t3.ops
FROM table1 AS t1
LEFT JOIN table2 AS t2 ON t2.id = t1.id OR (t2.id IS NULL AND t2.id1 = t1.id)
LEFT JOIN table3 AS t3 ON t3.id = t1.id OR (t3.id IS NULL AND t3.id1 = t1.id)
WHERE EXISTS (
SELECT 1
FROM table2 AS t2
LEFT JOIN table3 AS t3 ON t3.id = t1.id OR (t3.id IS NULL AND t3.id1 = t1.id)
WHERE t1.id = t1.id
AND (t3.ops = 'w')
);