SQL查询重复记录

问题描述:

我有两张表。 我们称它们为table_A和table_B。SQL查询重复记录

Table_B包含table_A的ForeignKey。

Table_A 

ID   Name 
1   A 
2   B 
3   C 

Table_B 



ID   table_a_fk 
1   2 
2   3 

现在我想从table_a中获取所有名称如果table_b不包含table_a中记录的ID。

我与此查询试了一下:

SELECT a.name 
FROM table_a a, table_b b 
WHERE a.id != b.table_a_fk 

与此查询我得到正确的结果我刚得到这个结果像5倍,我不知道为什么。

希望有人能解释我。

你的查询创建你的两个表AB之间的cartesian product。这是笛卡尔产品,可以产生这些重复值。与NOT IN相反,你想用NOT EXISTS

SELECT a.name 
FROM table_a a 
WHERE NOT EXISTS (
    SELECT * 
    FROM table_b b 
    WHERE a.id = b.table_a_fk 
) 

表达的另一种方法是使用一个anti-join,这是最常见的SQL编写的反连接(only if table_b.table_a_fk is NOT NULL):

SELECT a.name 
FROM table_a a 
WHERE a.id NOT IN (
    SELECT b.table_a_fk 
    FROM table_b b 
) 

另一种不常见表达反连接的方法:

SELECT a.name 
FROM table_a a 
LEFT OUTER JOIN table_b b ON a.id = b.table_a_fk 
WHERE b.id IS NULL 

使用不同

SELECT distinct a.name 
FROM table_a a, table_b b 
WHERE a.id != b.table_a_fk 

或者更好的是...

Select distinct name 
from tableA a 
Where not exists (Select * from tableB 
        Where table_a_fk = a.id) 
+0

我对使用DISTINCT修复语义错误的查询的建议感到有点惊讶。另外,第二个查询也是错误的。 –

+0

@Lukas,虽然它可能看起来应该是唯一的,但在问题中没有什么可以支持'name'字段在数据集中是唯一的。因此,为避免输出中出现重复名称,必须使用不同的名称。你是正确的,第一个查询是丑陋的,但很难说任何有效的东西都是*错误*。这是在我的回答中,因为这是他在问题中提出的形式,所以基于他可以理解的内容的解决方案可能更有可能得到解决。 –

+0

让'table_a'包含'(1,A)'和'table_b'为空。你的第一个查询将返回任何内容而不是'A'。这是不对的。您的第二个查询对于OP建议的数据集是错误的。 –