2013-05-10 41 views
0

我试图构造以下性质的查询:如果x位于A和B的并集中,但不在C和D的并集中,则返回x多重联合声明和结果表的差异

例如:

table table table table 
+---+ +---+ +---+ +---+ 
| A | | B | | C | | D | 
+---+ +---+ +---+ +---+ 
| 1 | | 4 | | 2 | | 3 | 
| 2 | | 5 | | 3 | | 7 | 
| 3 | | 6 | +---+ +---+ 
| 4 | | 7 | 
+---+ +---+ 

我要寻找这个返回:

+---+ 
| E | 
+---+ 
| 1 | 
| 4 | 
| 5 | 
| 6 | 
+---+ 

我已经试过:

SELECT * from A 
union 
SELECT * from B 
WHERE * not in 
(SELECT * from C 
union 
SELECT * from D) 

,但我想我的语法不正确。任何关于如何解决这个问题的建议都将受到极大的赞赏。

回答

1

我会这样写查询:

SELECT * 
FROM A 
WHERE A.ID NOT IN (SELECT ID FROM C) 
     AND A.ID NOT IN (SELECT ID FROM D) 
UNION 
SELECT * 
FROM B 
WHERE B.ID NOT IN (SELECT ID FROM C) 
     AND B.ID NOT IN (SELECT ID FROM D) 

你也可以写这样的:

SELECT * 
FROM 
    (SELECT * FROM A UNION SELECT * FROM B) s 
WHERE 
    ID NOT IN (SELECT ID FROM C UNION SELECT ID FROM D) 

请参阅小提琴here。您可能想要使用UNION ALL而不是UNION来删除重复项。

+0

这个技巧。谢谢! – 2013-05-10 10:49:54

2

试试这个:

SELECT u1.col1 
FROM (SELECT col1 from A union SELECT col1 from B) u1 
LEFT OUTER JOIN (SELECT col1 from C union SELECT col1 from D) u2 
ON u1.col1 = u2.col1 
WHERE u2.col1 IS NULL 

参见SQLFiddle演示。

该查询执行两个联合结果的左外部联接,然后过滤掉其中一个联合结果中缺少的联合结果。

+0

谢谢@Aziz。我相信这会做到这一点,但另一个答案更容易理解。 – 2013-05-10 10:50:54

1

“联合”命令是查询分隔符。这意味着它是一个查询之前发生的事情,并且它是另一个查询之后发生的事情。因此,您的WHERE子句仅适用于第二个查询(从B选择*)。

根据您的SQL平台,您可能能够将WHERE子句复制到UNION之前,因此它适用于这两个查询。或者,您可能需要使用JOIN或EXCEPTION JOIN或EXISTS,以获得您想要的。

+0

谢谢你的信息。 – 2013-05-10 10:50:10