两张表筛选相同数据和不同数据

本文介绍了SQLSERVER2005及以上版本中使用EXCEPT和INTERSECT运算符比较两张数据库表数据的方法,以及SQLSERVER2000中使用Exists的比较方式,并通过示例数据进行了演示。

项目中经常会对两张数据库表的数据进行比较,选出相同的数据或者不同的数据。在SQL SERVER 2000中只能用Exists来判断,到了SQL SERVER 2005以后可以采用EXCEPT和INTERSECT运算符比较两张表的数据。

EXCEPT运算符返回由EXCEPT运算符左侧的查询返回、而又不包含在右侧查询所返回的值中的所有非重复值。

INTERSECT返回由INTERSECT运算符左侧和右侧的查询都返回的所有非重复值。

例如有表A和B,其建表和数据脚本如下:

if object_id('[a]') is not null drop table [a]
go 
create table [a]([tel_no] bigint,[cost] int)
insert [a]
select 13800000000,38 union all
select 13823400000,56 union all
select 13800056400,88 union all
select 13800230000,28 union all
select 13802300000,18 union all
select 13822220000,68 union all
select 13844400000,98 union all
select 13833330000,35 union all
select 13822220000,31 union all
select 13811110000,32
--> 测试数据:[b]
if object_id('[b]') is not null drop table [b]
go 
create table [b]([tel_no] bigint)
insert [b]
select 13800000000 union all
select 13823400000 union all
select 13800051230 union all
select 13800230123
现在要查出两张表相同的数据和两张表不同的数据,如果在SQL SERVER 2005以上版本:

--相同数据
select tel_no  
from a
intersect
select tel_no 
from b

--不同数据
select tel_no  
from b
except
select tel_no 
from a

如果是SQL SERVER 2000

SELECT * FROM b WHERE EXISTS(SELECT 1 FROM a WHERE tel_no=b.tel_no)
 
SELECT * FROM b WHERE NOT EXISTS(SELECT 1 FROM a WHERE tel_no=b.tel_no)

两张方法得到的结果都是一样的:


<think>我们有两张,假设AB,它们都有一个数值类型的字段(比如叫做`value`)。我们想要找出只在B中出现,但不在A中出现的值。具体到问题中的例子:A有1,2,4;B有1,2,3,4。我们想找出3,因为它只在B中,不在A中。 方法:使用左连接(LEFT JOIN)或使用子查询(NOT IN 或 NOT EXISTS)都可以实现。 方案1:使用LEFT JOIN 思路:将B左连接A,连接条件是相同的值。然后,找出A中没有匹配的记录(即A的对应字段为NULL),那么这些记录在B中的值就是A中没有的。 SQL语句示例: ```sql SELECT DISTINCT B.value FROM tableB B LEFT JOIN tableA A ON B.value = A.value WHERE A.value IS NULL; ``` 方案2:使用NOT IN 思路:直接选择B中那些不在A中的值。 SQL语句示例: ```sql SELECT DISTINCT value FROM tableB WHERE value NOT IN (SELECT value FROM tableA); ``` 注意:如果A中的value字段有NULL值,那么NOT IN子查询可能会出现问题(因为NOT IN遇到NULL会返回未知,导致结果不正确)。为了避免这种情况,我们可以使用NOT EXISTS,它对于NULL是安全的。 方案3:使用NOT EXISTS ```sql SELECT DISTINCT B.value FROM tableB B WHERE NOT EXISTS (SELECT 1 FROM tableA A WHERE A.value = B.value); ``` 根据问题描述,我们只需要找出在B中但不在A中的值(即3)。以上三种方法都可以,但考虑到可能有NULL值的情况,推荐使用LEFT JOIN或NOT EXISTS。 另外,如果两张的结构不同,字段名不一样,那么需要调整字段名。这里假设两张都有一个名为`value`的字段。 示例数据A: value 1 2 4 B: value 1 2 3 4 执行上述任一查询,都会返回3。 注意:如果B中有重复的3,我们使用DISTINCT来去重,只返回一个3。 如果问题反过来,要找出A中有而B中没有的值,只需将上述查询中的AB互换即可。 因此,根据用户需求,我们给出三种方法,用户可以根据实际情况选择。</think>在MySQL中查询两张中不重复数据(即仅存在于一张中的数据),可以使用以下三种高效方法: ### 方法1:使用LEFT JOIN + UNION(推荐) ```sql -- 仅存在于B的数据 SELECT B.value AS unique_value, '仅B存在' AS source FROM tableB B LEFT JOIN tableA A ON B.value = A.value WHERE A.value IS NULL UNION ALL -- 合并结果集 -- 仅存在于A的数据 SELECT A.value AS unique_value, '仅A存在' AS source FROM tableA A LEFT JOIN tableB B ON A.value = B.value WHERE B.value IS NULL; ``` **说明**: 1. 第一部分获取B独有的数据:通过左连接A,筛选出A中不存在的记录[^1][^4] 2. 第二部分获取A独有的数据:原理同上但方向相反 3. `UNION ALL` 合并结果并保留重复记录(如需去重改用`UNION`) 4. 结果包含来源标识字段`source` ### 方法2:使用NOT EXISTS子查询 ```sql -- 仅B存在的数据 SELECT value AS unique_value FROM tableB WHERE NOT EXISTS ( SELECT 1 FROM tableA WHERE tableA.value = tableB.value ) UNION ALL -- 仅A存在的数据 SELECT value AS unique_value FROM tableA WHERE NOT EXISTS ( SELECT 1 FROM tableB WHERE tableB.value = tableA.value ); ``` **优势**: - 对NULL值安全(优于`NOT IN`)[^3] - 执行效率高,尤其在大数据场景[^2] ### 方法3:使用FULL OUTER JOIN(MySQL 8.0+) ```sql SELECT COALESCE(A.value, B.value) AS unique_value, CASE WHEN A.value IS NULL THEN '仅B存在' WHEN B.value IS NULL THEN '仅A存在' END AS source FROM tableA A FULL OUTER JOIN tableB B ON A.value = B.value WHERE A.value IS NULL OR B.value IS NULL; ``` **说明**: - `FULL OUTER JOIN` 返回两所有记录 - `COALESCE()` 合并两字段 - `WHERE` 子句过滤掉匹配记录[^1][^4] > **性能优化建议**: > 1. 在`value`字段创建索引:`CREATE INDEX idx_value ON tableA(value)` > 2. 大数据使用`EXPLAIN`分析执行计划 > 3. 优先选择`NOT EXISTS`或`LEFT JOIN`方案[^2] > 4. 避免在WHERE子句中使用函数操作字段 ### 示例结果 假设: - A:1, 2, 4 - B:1, 2, 3, 4 查询结果: ``` unique_value | source -------------|----------- 3 | 仅B存在 ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值