如何从一个表中选择不存在于另一个表中的所有记录?

table1 (id, name)
Table2 (id, name)

查询:

SELECT name
FROM table2
-- that are not in table1 already
1298164 次浏览
SELECT t1.name
FROM table1 t1
LEFT JOIN table2 t2 ON t2.name = t1.name
WHERE t2.name IS NULL

这里发生了什么?

一个:从概念上讲,我们从table1中选择所有行,对于每一行,我们尝试在table2中为name列找到具有相同值的行。如果没有这样的行,我们就将结果的table2部分留空。然后,通过只选择结果中匹配行不存在的行来限制选择。最后,我们忽略结果中除了name列之外的所有字段(从table1开始,我们确定它存在)。

虽然它可能不是在所有情况下性能最好的方法,但它应该可以在试图实现ANSI 92 SQL的每个数据库引擎中工作

你可以选择

SELECT name
FROM table2
WHERE name NOT IN
(SELECT name
FROM table1)

SELECT name
FROM table2
WHERE NOT EXISTS
(SELECT *
FROM table1
WHERE table1.name = table2.name)

请参阅这个问题以获得3种完成此任务的技术

这是纯集合论,你可以通过minus操作来实现。

select id, name from table1
minus
select id, name from table2

我没有足够的代表点数来投票给froadie的回答。但是我不同意关于EYZ1的评论。以下答案:

SELECT name
FROM table2
WHERE name NOT IN
(SELECT name
FROM table1)

在实践中效率更高。我不知道为什么,但我对800k+的记录进行了运行,上面发布的第二个答案的优势是巨大的。只有我的0.02美元。

小心陷阱。如果Table1中的Name字段包含null,则您将处于意外状态。 更好的是:< / p >
SELECT name
FROM table2
WHERE name NOT IN
(SELECT ISNULL(name ,'')
FROM table1)

你可以在mssql中使用EXCEPT或在oracle中使用MINUS,它们是相同的:

http://blog.sqlauthority.com/2008/08/07/sql-server-except-clause-in-sql-server-is-similar-to-minus-clause-in-oracle/ < a href = " http://blog.sqlauthority.com/2008/08/07/sql-server-except-clause-in-sql-server-is-similar-to-minus-clause-in-oracle/ " > < / >

那对我来说很有用

SELECT *
FROM [dbo].[table1] t1
LEFT JOIN [dbo].[table2] t2 ON t1.[t1_ID] = t2.[t2_ID]
WHERE t2.[t2_ID] IS NULL

以下是对我最有效的方法。

SELECT *
FROM @T1
EXCEPT
SELECT a.*
FROM @T1 a
JOIN @T2 b ON a.ID = b.ID

这比我试过的其他方法快了一倍多。

我将在正确答案....中转发(因为我还没有酷到可以评论)以防有人觉得需要更好的解释。

SELECT temp_table_1.name
FROM original_table_1 temp_table_1
LEFT JOIN original_table_2 temp_table_2 ON temp_table_2.name = temp_table_1.name
WHERE temp_table_2.name IS NULL

在mySQL中,我看到FROM中的语法需要在表名之间使用逗号,但在sqlLite中,它似乎更喜欢空格。

底线是,当你使用不好的变量名时,它会留下问题。我的变量应该更有意义。应该有人解释一下为什么我们需要逗号或不需要逗号。

SELECT <column_list>
FROM TABLEA a
LEFTJOIN TABLEB b
ON a.Key = b.Key
WHERE b.Key IS NULL;

enter image description here

https://www.cloudways.com/blog/how-to-join-two-tables-mysql/

看到查询:

SELECT * FROM Table1 WHERE
id NOT IN (SELECT
e.id
FROM
Table1 e
INNER JOIN
Table2 s ON e.id = s.id);

从概念上讲是:在子查询中获取匹配的记录,然后在主查询中获取不在子查询中的记录。

首先定义表的别名,如t1t2。 然后得到第二个表的记录。 之后,使用where条件匹配该记录:

SELECT name FROM table2 as t2
WHERE NOT EXISTS (SELECT * FROM table1 as t1 WHERE t1.name = t2.name)

我尝试了以上所有的解决方案,但它们都不适合我。下面的查询对我有用。

SELECT NAME
FROM   table_1
WHERE  NAME NOT IN
(SELECT    a.NAME
FROM      table_1 AS a
LEFT JOIN table_2 AS b
ON        a.NAME = b.NAME
WHERE     any further condition);


以上所有查询在大表上都非常慢。战略需要改变。这里有我用于我的DB的代码,你可以音译改变字段和表名。

这就是策略:创建两个隐式临时表并将它们合并。

  1. 第一个临时表来自第一个原始表的所有行选择,您想控制的字段不在第二个原始表中。
  2. 第二个隐式临时表包含两个原始表的所有行,这些行与您想控制的列/字段的相同值匹配。
  3. 合并的结果是,如果两个原始表(一个来自第一个选择,第二个来自第二个选择)上的值匹配,那么一个表具有多个具有相同控制字段值的行,并且如果第一个原始表的值与第二个原始表的任何值不匹配,则只有一行具有控制列值。
  4. 分组并计数。当计数为1时,没有匹配,最后,您只选择计数等于1的行。

看起来并不优雅,但它比上面所有的解决方案都要快几个数量级。

重要提示:使列上的INDEX被检查。

SELECT name, source, id
FROM
(
SELECT name, "active_ingredients" as source, active_ingredients.id as id
FROM active_ingredients


UNION ALL
        

SELECT active_ingredients.name as name, "UNII_database" as source, temp_active_ingredients_aliases.id as id
FROM active_ingredients
INNER JOIN temp_active_ingredients_aliases ON temp_active_ingredients_aliases.alias_name = active_ingredients.name


) tbl
GROUP BY name
HAVING count(*) = 1
ORDER BY name

你可以使用以下查询结构:

# EYZ0

表1:

id 的名字
1 阿米特
2 Sagar

表二:

id fk_id 电子邮件
1 1 amit@ma.com

输出:

的名字
Sagar