MySQL中的替代except方法

37

我必须在MySQL中编写像这样的查询:

SELECT * 
FROM Tab1
EXCEPT
SELECT * 
FROM Tab1 
WHERE int_attribute_of_Tab1>0

但是MySQL不支持关键字EXCEPT。是否有一种标准模式来正确使用另一个在MySQL中模拟except的运算符?

但是MySQL不支持关键字EXCEPT,是否有其他运算符可以在MySQL中模拟except,并且是否有标准的用法?


1
肯定是SELECT * FROM Tab1 WHERE int_attribute_of_Tab1 = 0,对吧?或者第二个select中的tab1应该改为tab2? - P.Salmon
7个回答

46

您可以使用 NOT IN。

SELECT * 
FROM Tab1
WHERE id  NOT IN (
    SELECT id 
    FROM Tab1 
    WHERE int_attribute_of_Tab1>0
)

2
如果我有两列,似乎无法正常工作: select distinct col1, col2 from Tab1 where col1, col2 not in(select distinct col1, col2 from Tab2) 你知道我做错了什么吗? - MrZH6
1
如果你还在想,答案是不行的。在子查询中,你不能选择多列作为比较对象,因为它必须跟主查询中的单个列(这里是 col2)进行比较。但是你可以在派生表等其他子查询中选择多列。 - AymDev

5

试试这个

SELECT * 
FROM Tab1
WHERE [....] NOT EXISTS 
(SELECT * 
FROM Tab1 
WHERE int_attribute_of_Tab1>0) 

2
您可以使用多个NOT IN操作符以及AND操作符来处理多列数据。例如:
SELECT col1, col2 FROM table1 WHERE col1 NOT IN(SELECT col1 FROM table2) AND col2 NOT IN(SELECT col2 FROM table2)...;

1
自从 MySQL 版本 8.0.31 更新 以来,EXCEPT 运算符已经可以在这个 DBMS 中使用。如果你被允许更新 MySQL 版本,你就可以自由地使用这种表示法:
SELECT * FROM Tab1
EXCEPT
SELECT * FROM Tab1 
WHERE int_attribute_of_Tab1>0

1

一些定义 SqlServer https://learn.microsoft.com/en-us/sql/t-sql/language-elements/set-operators-except-and-intersect-transact-sql EXCEPT 返回左侧查询中不与右侧查询返回的任何唯一值。 PLsql https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries004.htm MINUS 使用MINUS运算符将结果组合起来,仅返回第一个查询返回但第二个查询未返回的唯一行。

对于MySQL的学究式翻译可能是

 SELECT distinct t1.* 
FROM Tab1 as t1
left outer join
(SELECT * 
FROM Tab1 
WHERE int_attribute_of_Tab1>0) as t2 on t1.id = t2.id
where t2.id is null;

假设有一个id列,我不想在很多列上使用distinct。

4
即使SQLite支持EXCEPT,也很不幸。 - Polluks

0
如果Tab1有一个主键(例如ID),那么您可以像这样使用NOT EXISTS来引用自身:
SELECT * 
FROM Tab1 AS t1
WHERE NOT EXISTS (
    SELECT 1 
    FROM Tab1 AS t2
    WHERE t2.ID = t1.ID
      AND t2.int_attribute_of_Tab1 > 0
)

但在这种情况下,这有点毫无意义。
而且这不是EXCEPT/MINUS试图做的事情。
(排除相同的行)

问题的查询使用了两次相同的表格和EXCEPT
因此,在Tab1上反转WHERE条件将会得到相同的结果。

SELECT * 
FROM Tab1 
WHERE (int_attribute_of_Tab1 <= 0 OR int_attribute_of_Tab1 IS NULL) 

如果这是两个不同的表,则为此。
SELECT t1col1, t1col2, t1col3
FROM Table1
EXCEPT
SELECT t2col4, t2col5, t2col6
FROM Table2
WHERE int_attribute_of_Tab1 > 0

可以通过比较每个选定的列来替换

SELECT DISTINCT t1col1, t1col2, t1col3
FROM Table1 AS t1
WHERE NOT EXISTS (
    SELECT 1 
    FROM Table1 AS t2
    WHERE t2.t2col4 = t1.t1col1
      AND t2.t2col5 = t1.t1col2
      AND t2.t2col6 = t1.t1col3
      AND t2.int_attribute_of_Tab1 > 0
)

0

我发现了这个解决方案,但它考虑了所有字段,不会是一个简单的select *。

假设您在一个表tbl_tab中有字段id、name、att1、att2、fin_year,其中有50条记录的fin_year=2022和25条记录的fin_year=2023。

现在要获取tab1中除fin_year 20233之外的所有fin_year 2022的数据,需要执行以下操作。

select * from tbl_tab 
where fin_year=2022 and id not in (
select t1.id 
from tbl_tab t1 
inner join tbl_tab t2 
   on t2.name=t1.name
   and t2.att1=t1.att1
   and t2.att2=t1.att2
where t1.fin_year=2022
and t2.fin_year=2023);

这相当于

select name, att1, att2, fin_year from tbl_tab where fin_year=2022
except 
select name , att1, att2, fin_year from tbl_tab where fin_year=2023;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接