mysql - 正确替换 MySQL 服务器中的循环
问题描述
我有这张桌子:
我想找到每个年龄段出现最多的级别,例如 18 岁出现最多的级别是“FR”,而 19 岁是“SO”。
我的尝试:
SELECT X.AGE, X.LEVEL FROM
( SELECT S.AGE, S.LEVEL FROM STUDENT S WHERE S.AGE = 18) AS X
GROUP BY X.LEVEL
ORDER BY COUNT(*) DESC LIMIT 1;
我得到这个结果:
SELECT DISTINCT S.AGE FROM STUDENT S;
如何在知道我被阻止使用 while 循环的情况下迭代他们在此列表中的所有不同年龄。
解决方案
在 MySQL 8.0 之前,您必须使用自连接。
首先,您使用计数提取年龄和级别。
SELECT AGE, LEVEL, COUNT(*) AS C FROM STUDENT GROUP BY AGE, LEVEL
这让你说,
18 FR 2
18 SR 5
18 XX 5
19 FR 1
从中,您选择每个年龄的最大值 - 但您只想要一行,并且当年龄为 18 时,SR 和 XX 的最大值都为 5。否则,您可以使用自联接,首先选择"18 5" 使用 MAX() 然后再次加入以获得对应于 (18, 5) 的 LEVEL —— 仅,这里有两个级别可以匹配。当然你可以使用另一个 MAX。
SELECT A1.AGE, MAX(A2.LEVEL) FROM
( SELECT AGE, MAX(C) AS M FROM ( the query above ) AS A0 GROUP BY AGE ) AS A1
JOIN
( SELECT AGE, MAX(C) AS M FROM ( the query above ) AS A0 GROUP BY AGE ) AS A2
ON (A1.AGE = A2.AGE AND A1.M = A2.M)
或者您可以使用 hack 来限制子查询和自联接的数量:
SELECT AGE, SUBSTRING_INDEX(MAX(CONCAT(LPAD(C, 5, '0'), ':', LEVEL), ':', -1)) AS LEVEL FROM (
SELECT AGE, LEVEL, COUNT(*) AS C FROM STUDENT GROUP BY AGE, LEVEL
) AS INT GROUP BY AGE
该复杂表达式将首先将数字和级别连接到一个字符串中,以便“1 FR”和“15 SR”变为“00001:FR”和“00015:SR”,从而允许按字典顺序进行比较。然后 MAX 会按字母顺序提取最大值,现在也和数字顺序一样,数字相等时使用 LEVEL。所以你现在会得到
18 00005:XX
最后 SUBSTRING_INDEX 将采用字符串的最后一个元素,以冒号分隔,因此是所需的“XX”值。
推荐阅读
- java - 一个表单中的多个提交按钮
- android - 如何在 Android Java 中序列化 Firestore 时间戳?
- javascript - 点击函数内部的事件在点击外部触发
- javascript - Node.js - process.exit 并将整个 console.log 消息附加到文本文件中
- controller - Metrics/AbcSize:创建的分配分支条件大小太高。[15.17/15]
- typescript - 用于在 VS Code 中以捷克语在 TypeScript 中显示错误消息的语言环境
- hadoop - 文件传输到 HDFS
- python - 如何使用 TensorFlow 操作排除图像圆圈之外的所有值?
- python - 在 Pandas DataFrame 中添加从现有列和 API 调用计算的列
- java - 如何使用域发现模式在 Payara Server 中创建域数据网格?