Sql 让并集显示彼此旁边的值,而不是彼此下面的值
我得到了一个SQL查询,它显示了两个表中的值。现在,我想让这个表从两个不同的表中选择彼此之外的值。这是我现在的问题:Sql 让并集显示彼此旁边的值,而不是彼此下面的值,sql,sql-server,Sql,Sql Server,我得到了一个SQL查询,它显示了两个表中的值。现在,我想让这个表从两个不同的表中选择彼此之外的值。这是我现在的问题: (select i1,i2 from t1 except select i1,i2 from t2) union all (select i1,i2 from t2 except select i1,i2 from t1) 这是我的示例数据: 表1中的数据: i1 i2 --------- | 1 | 1 | --------- | 2 | 2 | --------- |
(select i1,i2 from t1
except
select i1,i2 from t2)
union all
(select i1,i2 from t2
except
select i1,i2 from t1)
这是我的示例数据:
表1中的数据:
i1 i2
---------
| 1 | 1 |
---------
| 2 | 2 |
---------
| 2 | 3 |
---------
表2中的数据:
i1 i2
---------
| 1 | 1 |
---------
| 2 | 3 |
---------
| 2 | 4 |
---------
结果:
---------
| 2 | 2 | << this one comes from table 1
---------
| 2 | 4 | << this one comes from table 2
---------
您可以使用
交叉联接
和不存在
来执行此操作:
SELECT *
FROM t1 a
CROSS JOIN t2 b
WHERE NOT EXISTS (SELECT 1
FROM t2 c
WHERE a.i1 = c.i1
AND a.i2 = c.i2
)
AND NOT EXISTS (SELECT 1
FROM t1 c
WHERE b.i1 = c.i1
AND b.i2 = c.i2
)
交叉连接
将一个表中的每条记录与另一个表中的每条记录连接起来,因此返回每一行的组合NOT EXISTS
用于从t1
中筛选出出现在t2
中的记录,反之亦然。对于第二个NOT EXISTS
我认为最好的方法是使用完全连接,然后使用NULL
数据执行WHERE
。因为如果您进行交叉联接
,您将获得比您需要的更多的数据
SELECT *
FROM t1
FULL JOIN t2
ON t1.i1 = 2.i1
AND t1.i2 = t2.i2
WHERE t1.Id IS NULL
OR t2.Id IS NULL
我将用一个例子来解释:
IF OBJECT_ID('tempdb..#t1') IS NOT NULL
DROP TABLE #t1
CREATE TABLE #t1
(
Id INT IDENTITY,
i1 INT,
i2 INT
)
INSERT INTO #t1
(
i1,i2
)
VALUES
(1,1)
,(2,2)
,(2,3)
,(2,6)
SELECT * FROM #t1
IF OBJECT_ID('tempdb..#t2') IS NOT NULL
DROP TABLE #t2
CREATE TABLE #t2
(
Id INT IDENTITY,
i1 INT,
i2 INT
)
INSERT INTO #t2
(
i1,i2
)
VALUES
(1,1)
,(2,3)
,(2,4)
,(2,5)
,(2,7)
SELECT * FROM #t2
SELECT *
FROM #t1
FULL JOIN #t2
ON #t1.i1 = #t2.i1
AND #t1.i2 = #t2.i2
WHERE #t1.Id IS NULL
OR #t2.Id IS NULL
SELECT *
FROM #t1 a
CROSS JOIN #t2 b
WHERE NOT EXISTS (SELECT 1
FROM #t2 c
WHERE a.i1 = c.i1
AND a.i2 = c.i2
)
AND NOT EXISTS (SELECT 1
FROM #t1 c
WHERE b.i1 = c.i1
AND b.i2 = c.i2
)
结果
在第一种情况下,您将得到5条记录,因为(2,2)和(2,6)在t2中不存在,而(2,4)、(2,5)、(2,7)在t1中不存在。所以你会有5个结果
Id i1 i2 Id i1 i2
----------- ----------- ----------- ----------- ----------- -----------
2 2 2 NULL NULL NULL
4 2 6 NULL NULL NULL
NULL NULL NULL 3 2 4
NULL NULL NULL 4 2 5
NULL NULL NULL 5 2 7
(5 row(s) affected)
然而,在交叉连接中,你会得到6个结果,因为你会得到一个笛卡尔积。2x3=6
试一试
这叫做“加入”。这不是目的,也不是工会的运作方式。使用带有NOT EXISTS子句的join。好吧,我明白了,对不起,伙计们,我应该删除这个问题吗?我不认为这是个坏问题,只是很难理解您的数据示例,如果它们有列标题可能会更好。在这一点上与@HartCO达成一致。你只是因为问一些基本的问题而受到一些连续的投票人的反对,但是列标题会有很大帮助。如果用户有更多的数据,那么会返回比需要更多的记录。我会制作一个笛卡尔产品,我认为用户不需要。您可能低估了查询优化器,但我希望看到一个返回所需输出的替代方案。我曾想过使用完全联接,但要使“2,2”记录与“2,4”记录在同一行上,您必须使用
和或,然后,您仍然需要使用NOT EXIST
s过滤不需要的行。@HartCO感谢您的评论。我会检查的@哈特科是的,我同意你的看法。我要求用户提供更多细节,以防他添加更多记录。所以我可以更好地了解您想要的是什么。它返回的交叉连接结果相同,不是吗?
Id i1 i2 Id i1 i2
----------- ----------- ----------- ----------- ----------- -----------
2 2 2 NULL NULL NULL
4 2 6 NULL NULL NULL
NULL NULL NULL 3 2 4
NULL NULL NULL 4 2 5
NULL NULL NULL 5 2 7
(5 row(s) affected)
Id i1 i2 Id i1 i2
----------- ----------- ----------- ----------- ----------- -----------
2 2 2 3 2 4
2 2 2 4 2 5
2 2 2 5 2 7
4 2 6 3 2 4
4 2 6 4 2 5
4 2 6 5 2 7
(6 row(s) affected)
SELECT *
FROM
(
SELECT i1, i2
FROM t1
EXCEPT
SELECT i1, i2
FROM t2
) a,
(
SELECT i1, i2
FROM t2
EXCEPT
SELECT i1, i2
FROM t1
) b