我有两个表A和B 公用栏x
SELECT A.*
FROM A
LEFT JOIN B
ON A.x == B.x
WHERE A.z == "Hola" AND B.y IS NOT NULL;
我对与EXIST或LEFT JOIN WHERE子句相比为null会产生什么输出感到困惑。
如果我没记错的话,这需要A上的内容和A&B之间的相同之处,但排除B无效的地方,对吗?
答案 0 :(得分:1)
如果表包含以下值:
**Table1** **Table2**
ID Values ID Values
1 100 1 10
2 200 2 20
3 300 3 30
4 400 4 40
null 2000 null 3000
5 500
您的查询将返回以下内容:
具有:A.Id, A.table1_values, B.Table2_values
ID Table1_Values Table2_Values
1 100 10
2 200 20
3 300 30
4 400 40
5 500 null
a.*
的最终输出:
ID Table1_Values
1 100
2 200
3 300
4 400
5 500
null 2000
从此处复制的数据:left outer join with null values
答案 1 :(得分:1)
这是您的查询:
SELECT A.*
FROM A LEFT JOIN
B
ON A.x = B.x
WHERE A.z = 'Hola' AND B.y IS NOT NULL;
您需要分解查询。
结果集将只有A.Z = 'Hola'
。这是WHERE
子句中的重要过滤器。
然后,B.y IS NOT NULL
意味着两件事:B
中存在匹配项,而y
不是NULL
。因此,此查询等效于:
SELECT A.*
FROM A INNER JOIN
B
ON A.x = B.x
WHERE A.z = 'Hola' AND B.y IS NOT NULL;
使用内部联接,可以将WHERE
条件放入ON
中。那是风格问题。您无法使用LEFT JOIN
来做到这一点。
然后,“等价” EXISTS
查询将是:
SELECT A.*
FROM A
WHERE A.z = 'Hola' AND
EXISTS (SELECT 1 FROM B WHERE A.x = B.x AND B.y IS NOT NULL);
这些并不完全相同。如果JOIN
中有多个匹配项,则带有A
的版本将返回B
的重复行。由于您仅从A
中进行选择,因此可能不希望重复,因此建议使用EXISTS
查询。
答案 2 :(得分:0)
非常简单但很好的问题。
让我们进行转换并找到答案
WHERE
上的B.y
谓词移至JOIN
子句SELECT
A.*
FROM
A
LEFT JOIN B ON A.x == B.x
AND B.y IS NOT NULL
WHERE
A.z == "Hola";
现在我们可以:
LEFT JOIN
转换为UNION ALL
和JOIN-
表达式的NOT EXISTS-
LEFT JOIN
-> JOIN
+ NOT EXISTS
SELECT A.*
FROM A
JOIN B ON A.x == B.x
AND B.y IS NOT NULL
WHERE
A.z == "Hola"
UNION ALL
SELECT A.*
FROM A
WHERE
A.z == "Hola"
AND NOT EXISTS(
SELECT * FROM B
WHERE A.x = B.x
AND B.y IS NOT NULL
)
看看这些表达式,我们可以看到:
NOT NULL
-UNION ALL
下半部分的字段变得多余答案 3 :(得分:0)
您可以尝试如下操作:
select a.*
from a
where a.z = "Hola"
and exists (select 1
from b
where b.y is not null
and b.x = a.x);