如何连接表以包含与另一个表中的值完全匹配的结果,或者根本不包含结果?

时间:2014-08-02 05:54:15

标签: mysql sql join

我有两张桌子。我要么需要与第二个表中的特定值相关联的结果,要么根本不存在。我怎么能做到这一点?

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 = 0TableA的值与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
        );

你推荐什么?

5 个答案:

答案 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会获得与ab之间匹配或不匹配的所有内容(同时仅在b value上获取信息}}不是0)。