请教一个关于 MySQL 子查询的问题

2021-06-10 19:58:41 +08:00
 s609926202

准备一张表:t_user

首先,按年龄和性别进行分组:select id from t_user where 1=1 group by sex,age,有 4 条结果,ID 分别为:3,5,7,9

然后,我按照子查询的方式:select * from t_user where id in (select id from t_user where 1=1 group by sex,age) order by id,却超出了 4 条结果,而子查询体正是上一个分组查询的结果。

所以请教一下,为何把分组查询的结果放到子查询,再次查询时结果不是分组查询的结果呢?

1775 次点击
所在节点    数据库
19 条回复
JasonLaw
2021-06-10 20:37:07 +08:00
描述一下你的重现步骤吧,不然都是靠猜。还有,你的写法真的很奇怪。
c6h6benzene
2021-06-10 21:07:03 +08:00
where 1=1 是为了啥…

话说我主要写 t-sql 的,看到 group by 没有聚合函数总觉得浑身不自在。
aragakiyuii
2021-06-10 22:07:34 +08:00
select 的 column 不应该是在 group by 里吗?

https://dev.mysql.com/doc/refman/8.0/en/group-by-handling.html

If ONLY_FULL_GROUP_BY is disabled, a MySQL extension to the standard SQL use of GROUP BY permits the select list, HAVING condition, or ORDER BY list to refer to nonaggregated columns even if the columns are not functionally dependent on GROUP BY columns. This causes MySQL to accept the preceding query. In this case, the server is free to choose any value from each group, so unless they are the same, the values chosen are nondeterministic, which is probably not what you want. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause. Result set sorting occurs after values have been chosen, and ORDER BY does not affect which value within each group the server chooses. Disabling ONLY_FULL_GROUP_BY is useful primarily when you know that, due to some property of the data, all values in each nonaggregated column not named in the GROUP BY are the same for each group.
Euthpic
2021-06-10 23:37:46 +08:00
如果 id 是唯一值,那么第二条查询的数目等于第一条,如果不是就大于第一条.

@c6h6benzene 为了 SQL 拼装,后面要加条件的话都是 and xxx=aaa.
NotFoundEgg
2021-06-10 23:50:06 +08:00
可以考虑把子查询的结果 放在 select * from t_user where id in () 里试下有几条
T0m008
2021-06-11 07:34:41 +08:00
你这是要按照年龄性别排序么?你先描述一下,你这查询写的没什么意义
xiangyuecn
2021-06-11 09:25:06 +08:00
一看就知道是低版本 mysql,居然无理取闹的支持 select AA group by BB 😂 mysql 自己都看不下去了
sanggao
2021-06-11 09:33:25 +08:00
@xiangyuecn 高版本也支持,5.6 5.7 5.8 都支持 也有啥问题?
enderftt
2021-06-11 09:46:25 +08:00
仅有 mysql 有这种写法 你把 sex ,age 也放到结果列里面就知道了
s609926202
2021-06-11 10:06:23 +08:00
@T0m008 实际查询大概也是这个意思。
s609926202
2021-06-11 10:07:30 +08:00
@enderftt
放到结果列?
s609926202
2021-06-11 10:09:59 +08:00
@NotFoundEgg 子查询结果放在 select * from t_user where id in () 里,有几个 id 就有几条结果。
s609926202
2021-06-11 10:10:30 +08:00
@c6h6benzene where 中 1=1 查询全部结果
xiangyuecn
2021-06-11 10:16:29 +08:00
@sanggao #8 说的就是 5.x == 低版本😂
c6h6benzene
2021-06-11 10:44:33 +08:00
@s609926202 主要不写 1=1 也是全部结果,除非是后续有拼接需求,不然这部分就是多此一举。

就跟 @Euthpic 说的,你这 ID 可能会有重复,你看看每个 ID 有几条就知道了:

select id, COUNT(id) from t_user group by id
sanggao
2021-06-11 11:49:53 +08:00
@xiangyuecn 啥意思啊 这个语法 mysql 全部版本都支持,你说的是什么版本不支持?
sanggao
2021-06-11 11:50:57 +08:00
@xiangyuecn mysql 最高版本现在就是 5.8 也支持
kisick
2021-06-11 12:37:06 +08:00
@sanggao 5.7 以上,默认就不支持了,需要改配置文件
512357301
2021-06-12 12:53:01 +08:00
你是想取每个分组的第一个 id 对吧?
这种写法是第一次见,不过也可以理解,5.8 以下版本不支持开窗函数,只能这样写

你可以尝试把你的第一段 sql 作为左表,括起来后,别名 temp_a,然后 left join t_user 表,on temp_a.id = t_user.id
然后,select t_user.*

看下结果是否符合要求(想当于把子查询变成了虚拟表,效率应该也会高一些)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/782736

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX