选择不在多列中


75

我需要实现以下查询:

SELECT * 
FROM   friend 
WHERE  ( friend.id1, friend.id2 ) 
         NOT IN (SELECT id1, 
                        id2 
                 FROM   likes) 

但是NOT IN不能在多列上实现。如何编写此查询?



3
您的代码是有效的标准完整SQl-92语法。您只在问题中添加了“ sql”标签。如果您要使用的是特定产品(例如SQL Server),则应为其找到特定的标签(SQL Server,BTW不支持该语法)。
2011年

这会是OpenEdge吗?不幸的是开放边没有实现完整的SQL-92规范既不not innot exists工作,只有left join where = null战略将与OpenEdge工作。
布雷特·瑞安

Answers:


103

我不确定您是否考虑过:

select * from friend f
where not exists (
    select 1 from likes l where f.id1 = l.id and f.id2 = l.id2
)

仅当id1与id1相关联且id2与id2相关联而不同时与之相关时,它才有效。


以我为例。我只想排除在排除表中存在A和B列的行。SQL Server2016。–
russellhoff

它可与MySQL一起使用,而不是EXCEPT,因为MySQL不支持EXCEPT语法
Kamil Nekanowicz

2
如果id1或id2包含NULL值,则这在SQL Server中将不起作用,您需要使用select 1 from likes l where coalesce(f.id1, 0) = coalesce(l.id1, 0) and coalesce(f.id2, 0) = coalesce(l.id2, 0)
Coalesce

22

另一个神秘未知的RDBMS。您的语法在PostgreSQL中非常好。其他查询样式的执行速度可能更快(尤其是NOT EXISTS变体或LEFT JOIN),但您的查询完全合法。

NOT IN但是,在涉及任何NULL值时,请注意的陷阱:

有LEFT JOIN的变体:

SELECT *
FROM   friend f
LEFT   JOIN likes l USING (id1, id2)
WHERE  l.id1 IS NULL;

有关NOT EXISTS变体,请参见@Michał的答案。
对四个基本变体进行更详细的评估:


删除了简化的EXISTS。最好使用标准格式。
Erwin Brandstetter

3

我使用的方法可能看起来很愚蠢,但对我有用。我只是合并要比较的列并使用NOT IN:

SELECT *
FROM table1 t1
WHERE CONCAT(t1.first_name,t1.last_name) NOT IN (SELECT CONCAT(t2.first_name,t2.last_name) FROM table2 t2)

1
concat将提供错误的匹配。(即“ ab”,“ cd”和“ a”,“ bcd”)
mrm

因此,也许在中间添加一个分隔符,例如“ ab” +“ /” +“ cd”
vacolane

1
您可以使用保证不会被任何一列使用的分隔符来避免错误匹配,但是更大的问题是由于使用WHERE CONCAT,您的查询需要全表扫描。first_name或last_name列上的索引对查询计划者无用。
mrm

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.