大数据面试_找出A表存在但B表不存在的数据:方法与解析

1. LEFT JOIN + IS NULL(推荐)

语法

sql

SELECT a.*
FROM a
LEFT JOIN b ON a.id = b.id
WHERE b.id IS NULL;

特点
  • 原理:通过左连接保留A表所有记录,筛选B表中无匹配的记录(即B.id为NULL)。

  • 优点

    • 执行效率高(尤其在B.id有索引时)。

    • 对NULL值安全,无需额外处理。

  • 适用场景:大数据量、需返回A表全部字段。


2. NOT IN子查询(谨慎使用)

语法

sql

SELECT a.*
FROM a
WHERE a.id NOT IN (SELECT DISTINCT b.id FROM b);

特点
  • 原理:筛选A表中不在B表id集合中的记录。

  • 缺点

    • 若B.id存在NULL值,查询会返回空结果(因 NOT IN (NULL, ...) 逻辑失效)。

    • 子查询结果集大时性能较差。

  • 改进方案

    sql

    -- 显式排除NULL值
    SELECT a.*
    FROM a
    WHERE a.id NOT IN (SELECT b.id FROM b WHERE b.id IS NOT NULL);
    
    

3. 集合操作符(MINUS/EXCEPT)

语法

sql

-- Oracle/PostgreSQL
SELECT a.id FROM a
MINUS
SELECT b.id FROM b;

-- SQL Server
SELECT a.id FROM a
EXCEPT
SELECT b.id FROM b;

特点
  • 原理:直接取A表与B表的id差集。

  • 优点:语法简洁,适合仅需id字段的场景。

  • 缺点

    • 仅返回id字段,无法获取A表其他字段。

    • 不同数据库语法不同(如SQL Server用EXCEPT)。


4. NOT EXISTS子查询(推荐)

语法

sql

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

特点
  • 原理:逐行检查A表记录是否在B表中存在。

  • 优点

    • 对NULL值安全,无需过滤。

    • 性能优化潜力大(若B.id有索引,效率接近LEFT JOIN)。

  • 适用场景:需要返回A表全部字段,且B表有索引。


性能对比与选择建议

方法优点缺点推荐场景
LEFT JOIN高效,支持全字段返回需明确关联条件通用场景,大数据量
NOT IN语法简单NULL值敏感,子查询性能差B表无NULL且数据量小
MINUS/EXCEPT简洁,适合单字段仅返回id字段,跨数据库语法差异仅需id字段
NOT EXISTS对NULL安全,支持索引优化语法稍复杂B表有索引或需逐行检查逻辑

示例验证

数据准备

sql

-- A表
CREATE TABLE a (id INT, name VARCHAR(10));
INSERT INTO a VALUES (1, 'A1'), (2, 'A2'), (3, 'A3');

-- B表
CREATE TABLE b (id INT);
INSERT INTO b VALUES (2), (NULL);

查询结果
  • LEFT JOIN:返回 (1, 'A1'), (3, 'A3')

  • NOT IN:若未过滤NULL,返回空;若过滤NULL,返回 (1, 'A1'), (3, 'A3')

  • MINUS:返回 1, 3

  • NOT EXISTS:返回 (1, 'A1'), (3, 'A3')


总结

  • 首选方案LEFT JOIN 或 NOT EXISTS,兼顾性能与安全性。

  • 避坑指南

    • 避免直接使用 NOT IN 处理含NULL值的子查询。

    • 使用集合操作符时注意字段限制和数据库兼容性。

  • 优化关键:为关联字段(如id)建立索引,定期更新统计信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据小塔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值