garlics
V2EX  ›  MySQL

MySQL 复杂的 in 子查询语句会导致筛选失效?

By garlics at 2021 年 4 月 26 日 · 3867 次点击

导入数据

CREATE TABLE test (
	id INT UNSIGNED auto_increment PRIMARY KEY,
	shop_id INT (11) UNSIGNED NOT NULL
);
INSERT INTO test (id, shop_id) VALUES (1, 1);
INSERT INTO test (id, shop_id) VALUES (2, 2);
INSERT INTO test (id, shop_id) VALUES (3, 3);
INSERT INTO test (id, shop_id) VALUES (4, 2);

使用语句查询,目的是找出每个 shop_id 下第一个 id

SELECT * FROM test WHERE id IN ( SELECT `t`.`id` FROM ( SELECT e.* FROM test e ORDER BY e.id DESC ) t GROUP BY `t`.`shop_id` );

结果第四条记录也被查询了出来,而子查询语句如果单独拉出来执行,结果是 1,2,3 。这是为什么?

14 条回复  •  2021-05-30 15:28:00 +08:00
fage108
   1
fage108  
   2021 年 4 月 26 日
```sql
SELECT * FROM test WHERE id IN ( SELECT `t`.`id` FROM ( SELECT e.* FROM test e ORDER BY e.id DESC ) t GROUP BY `t`.`id` );
```
你试试这个
7Qi7Qi
   2
7Qi7Qi  
   2021 年 4 月 26 日
select min(id), shop_id from test group by shop_id
2kCS5c0b0ITXE5k2
   3
2kCS5c0b0ITXE5k2  
   2021 年 4 月 26 日
SELECT * FROM test WHERE id IN ( SELECT `t`.`id`, `t`.`shop_id` FROM ( SELECT e.* FROM test e ORDER BY e.id DESC ) t GROUP BY `t`.`shop_id` );
2kCS5c0b0ITXE5k2
   4
2kCS5c0b0ITXE5k2  
   2021 年 4 月 26 日
子查询里面只返回了 t.id 不符合 group 条件.
garlics
   5
garlics  
OP
   2021 年 4 月 26 日
@emeab #4 但是子查询有两个,就报错了
@fage108 #1 还是不行
@7Qi7Qi #2 需求不是查出最小的 id,只是为了复现,我简化了问题
johnj
   6
johnj  
   2021 年 4 月 26 日
为啥要用 group 用了 group 又不出出现 group 后的字段 那是不对的
2kCS5c0b0ITXE5k2
   7
2kCS5c0b0ITXE5k2  
   2021 年 4 月 26 日
@garlics 我看错了 忽略我那 2 条.
xuanbg
   8
xuanbg  
   2021 年 4 月 26 日
SELECT `t`.`id` FROM ( SELECT e.* FROM test e ORDER BY e.id DESC ) t GROUP BY `t`.`shop_id`结果是不稳定的呀。改成:SELECT `shop_id`, min( `id`) as id FROM test GROUP BY `shop_id`
liangjx
   9
liangjx  
   2021 年 4 月 26 日
SELECT * FROM itest WHERE id IN (SELECT min(e.id) FROM itest e GROUP by e.shop_id );
liangjx
   10
liangjx  
   2021 年 4 月 26 日
min+group by 的意思是找出 group 中最小的那一项
zibber
   11
zibber  
   2021 年 4 月 26 日
我记得是 mysql 版本的问题 子查询里要加一个 limit 不然数据结果有问题
sycxyc
   13
sycxyc  
   2021 年 4 月 26 日
可能是优化器 BUG
加多一层 MariaDB10.5.8 结果正确

```sql
SELECT
*
FROM
test
WHERE
`id` IN (SELECT
*
FROM
(SELECT
`t`.`id`
FROM
(SELECT
e.*
FROM
test e
ORDER BY e.id) t
GROUP BY `t`.`shop_id`) AS tt);
```
512357301
   14
512357301  
   2021 年 5 月 30 日 via Android
5.8 及以上版本可以用开窗函数,用 shop_id 分区,id 升序,这样每个分区取第一条就行了
in 里套子查询。。。,执行效率不会拉胯吗?🙃
› MySQL 5.5 Community Server
› MySQL 5.6 Community Server
› Percona Configuration Wizard
› XtraBackup 搭建主从复制
Great Sites on MySQL
› Percona
› MySQL Performance Blog
› Severalnines
推荐管理工具
› Sequel Pro
› phpMyAdmin
推荐书目
› MySQL Cookbook
MySQL 相关项目
› MariaDB
› Drizzle
参考文档
› http://mysql-python.sourceforge.net/MySQLdb.html
© 2026 V2EX · 38ms · 3.9.8.5