以下有jf_a 和 jf_b表,请查找出jf_a 表中不存在jf_b表中的数据 的sql语句
看下面
desc jf_a; +-------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | name | varchar(255) | YES | | NULL | | | age | int(10) unsigned | YES | | 0 | | +-------+------------------+------+-----+---------+----------------+ jf_a表 +----+-------+------+ | id | name | age | +----+-------+------+ | 1 | jone2 | 11 | | 2 | luch2 | 22 | | 3 | jack | 0 | | 4 | jim | 0 | | 5 | james | 0 | +----+-------+------+ jf_b表结构 +-------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | a_id | int(10) unsigned | YES | | NULL | | +-------+------------------+------+-----+---------+----------------+ jf_b 数据 +----+------+ | id | a_id | +----+------+ | 1 | 3 | +----+------+
请查找到jf_a不在jf_b中的数据
select id,name from jf_a where id not in(select a_id from jf_b); +----+-------+ | id | name | +----+-------+ | 1 | jone2 | | 2 | luch2 | | 4 | jim | | 5 | james | +----+-------+ #然后通过explain 来看看执行结果: explain select id,name from jf_a where id not in(select a_id from jf_b) \G *************************** 1. row *************************** id: 1 select_type: PRIMARY table: jf_a type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 5 Extra: Using where *************************** 2. row *************************** id: 2 select_type: DEPENDENT SUBQUERY table: jf_b type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1 Extra: Using where 2 rows in set (0.00 sec)
使用 not in 这种方法,如果数据比较少还是可以的,如果数据特别多,执行时间比较长,不是一个较好的解决方案。
建议使用 join 来试试:
先普及一下join知识
left join 以左表为主 ,右表匹配不到以NULL 补齐
right join 以右表为主 左表匹配不到以NULL补齐 因为右表的数据都存在于左表,所以没有显示出null来。
inner join 两表都存在 才显示
mysql> #查找出b表不存在a表的中的数据 mysql> select * from jf_a as a left join jf_b as b on a.id=b.a_id; +----+-------+------+------+------+ | id | name | age | id | a_id | +----+-------+------+------+------+ | 1 | jone2 | 11 | NULL | NULL | | 2 | luch2 | 22 | NULL | NULL | | 3 | jack | 0 | 1 | 3 | | 4 | jim | 0 | NULL | NULL | | 5 | james | 0 | NULL | NULL | +----+-------+------+------+------+ 5 rows in set (0.00 sec) mysql> select * from jf_a as a right join jf_b as b on a.id=b.a_id; +------+------+------+----+------+ | id | name | age | id | a_id | +------+------+------+----+------+ | 3 | jack | 0 | 1 | 3 | +------+------+------+----+------+ 1 row in set (0.00 sec) mysql> select * from jf_a as a inner join jf_b as b on a.id=b.a_id; +----+------+------+----+------+ | id | name | age | id | a_id | +----+------+------+----+------+ | 3 | jack | 0 | 1 | 3 | +----+------+------+----+------+ 1 row in set (0.00 sec)
最后sql语句:
仔细观察可以发现,我们需要的结果集[1, 2, 4, 5]所对应的id1字段都是null。
这样,在查询语句中加入条件B.id is null,我们只需要A表中的数据,B表的数据忽略。
因此 添加 b.id is null
就是下面的结果了:
select a.id,a.name from jf_a as a left join jf_b as b on a.id=b.a_id where b.id is NULL; +----+-------+ | id | name | +----+-------+ | 1 | jone2 | | 2 | luch2 | | 4 | jim | | 5 | james | +----+-------+ 有这四条数据不在b表中。 那么来看看explain explain select a.id,a.name from jf_a as a left join jf_b as b on a.id=b.a_id where b.id is NULL \G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: a type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 5 Extra: *************************** 2. row *************************** id: 1 select_type: SIMPLE table: b type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1 Extra: Using where; Not exists 2 rows in set (0.00 sec) 看到数据都是全表扫描 类型是 simple
如果我们加一个索引呢? 在jf_b 表中 a_id 加一个 index 索引后,看看结果
explain select a.id,a.name from jf_a as a left join jf_b as b on a.id=b.a_id where b.id is NULL \G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: a type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 5 Extra: *************************** 2. row *************************** id: 1 select_type: SIMPLE table: b type: ref possible_keys: a_id key: a_id key_len: 5 ref: test.a.id rows: 1 Extra: Using where; Using index; Not exists 2 rows in set (0.00 sec)
如果A、B表的id、和B表的a_id都加了索引,那么join方式就能够命中索引
看到使用了 ref ,索引使用了a_id 在大量的数据下,效率是非常高的。