我有两张桌子。我要么需要与第二个表中的特定值相关联的结果,要么根本不存在。我怎么能做到这一点?
TableA TableB
id name table_a_id value
---------------- ---------------------
1 alpha 1 1
2 beta 2 0
3 gamma 3 1
4 delta 3 1
5 epsilon
期望的输出:
来自TableA
的所有行,其中TableB = 0
或TableA
的值与TableB
完全无关。
2 beta -- associated with 0 value on TableB
4 delta -- not in TableB at all
5 epsilon -- not in TableB at all
如何在一个查询中获得这些结果?
这是实现这一目标的低效方法:
SELECT *
FROM TableA a,TableB b
WHERE
a.id = b.table_a_id
AND a.id NOT IN (
SELECT table_a_id
FROM TableB
WHERE value != 0
);
你推荐什么?
答案 0 :(得分:1)
我会选择UNION并建议使用EXPLAIN来检查性能。
SELECT DISTINCT
a.*
FROM
TableA a
INNER JOIN
TableB b
ON
a.id = b.table_a_id
AND
b.value = 0
UNION ALL -- There can't be duplicates
SELECT
a.*
FROM
TableA a
LEFT JOIN
TableB b
ON
a.id = b.table_a_id
WHERE
b.table_a_id IS NULL;
答案 1 :(得分:0)
试试这个:
SELECT DISTINCT a.id, a.name
FROM
TableA a
LEFT JOIN TableB b ON a.id = b.table_a_id
WHERE
b.value = 0 or Isnull(b.value);
答案 2 :(得分:0)
我不认为OPs示例sql将返回所需的结果bc连接将排除ID 4和5.您可以使用左连接到tableb并检查其id是否为null,其值为0或者如果它为null:
select *
from tablea a
left join tableb b on bi.id = a.id
where b.value = 0 or b.id is null
请注意,如果value可以为空,则不希望使用它来检查左连接。假设id不可为空,那么如果b.id为null,那么我们知道表b中没有id与输出的表匹配id。
答案 3 :(得分:0)
首先想到的答案是这样的:
SELECT a.*
FROM TableA a
LEFT JOIN TableB b ON a.id = b.table_a_id
WHERE b.table_a_id IS NULL OR b.value = 0
它与JRLambert非常相似,但它测试b.table_a_id为NULL而不是b.value。这更加可靠,因为b.table_id是JOIN列...只有在TableB中没有匹配的行时才能为NULL。从你告诉我们的内容来看,b.value本身很可能是NULLable。
但是,如果TableB最多只能有一行具有相同的table_a_id和value = 0,那么这只能正常工作。否则,JOIN将为同一个TableA行显示多行,这似乎并不合适。
在这种情况下,您需要做一些不同的事情。您可以简单地添加DISTINCT,但仅当您没有从TableB中选择列时才能使用。
另一种方法是使用EXISTS:
SELECT *
FROM TableA a
WHERE NOT EXISTS (
SELECT b.table_a_id
FROM TableB b
WHERE b.table_a_id=a._id)
OR EXISTS (
SELECT b.table_a_id
FROM TableB b
WHERE b.table_a_id=a._id AND b.value=0)
您也可以使用UNION,但有数百万条记录我会避免使用它。
答案 4 :(得分:0)
我会用LEFT JOIN
和限制信息来做;在ON
部分。
SELECT a.*, b.* FROM TableA a
LEFT JOIN TableB b ON a.id = b.id AND b.value NOT IN (0)
LEFT JOIN
会获得与a
和b
之间匹配或不匹配的所有内容(同时仅在b
value
上获取信息}}不是0
)。