UNION后保留ORDER BY及Occupations表两类SQL查询问题求助
解决Occupations表的两个查询及UNION排序问题
嘿,我来帮你一步步搞定这两个SQL需求,还有UNION合并后如何保留各部分排序的问题!
1. 生成姓名+职业首字母的格式化列表
要得到AnActorName(A)这种格式的结果,核心就是字符串拼接加提取首字符。大多数数据库都支持LEFT函数取第一个字符,再用CONCAT把各部分拼起来,最后按姓名字母顺序排序就行:
示例SQL(适配MySQL、PostgreSQL、SQL Server等主流数据库):
SELECT CONCAT(Name, '(', LEFT(Occupation, 1), ')') AS formatted_entry FROM Occupations ORDER BY Name;
如果你用的是Oracle,把LEFT换成SUBSTR(Occupation, 1, 1)就可以了,其他逻辑不变。
2. 统计各职业出现次数并按次数升序排序
这个需要用GROUP BY按职业分组,再用COUNT(*)统计次数,排序的时候先按次数升序,次数相同的话按职业名称排序(避免结果混乱):
SELECT Occupation, COUNT(*) AS occurrence_count FROM Occupations GROUP BY Occupation ORDER BY occurrence_count ASC, Occupation ASC;
这里ORDER BY的两个条件,第一个保证次数少的在前,第二个保证同次数的职业按字母顺序排列,结果更规整。
3. UNION后保留各部分的排序规则
直接用UNION合并两个查询的话,外层的ORDER BY会统一排序整个结果集,如果你想让第一部分保持姓名排序,第二部分保持次数排序,就得给每个子查询加个“强制保留排序”的小技巧:
针对MySQL/PostgreSQL:
用LIMIT加一个极大值(比如MySQL的最大无符号整数),让数据库认为需要限制行数,从而保留子查询的排序:
-- 第一部分:格式化姓名列表,按姓名排序 (SELECT CONCAT(Name, '(', LEFT(Occupation, 1), ')') AS combined_result FROM Occupations ORDER BY Name LIMIT 18446744073709551615) UNION ALL -- 第二部分:职业统计,按次数升序排序 (SELECT CONCAT(Occupation, ': ', COUNT(*)) AS combined_result FROM Occupations GROUP BY Occupation ORDER BY COUNT(*) ASC, Occupation ASC LIMIT 18446744073709551615);
用UNION ALL而非UNION是因为两部分结果格式不同,不会有重复数据,UNION ALL性能更好。
针对SQL Server:
用TOP 100 PERCENT来取所有行,强制保留子查询的排序逻辑:
(SELECT TOP 100 PERCENT CONCAT(Name, '(', LEFT(Occupation, 1), ')') AS combined_result FROM Occupations ORDER BY Name) UNION ALL (SELECT TOP 100 PERCENT CONCAT(Occupation, ': ', COUNT(*)) AS combined_result FROM Occupations GROUP BY Occupation ORDER BY COUNT(*) ASC, Occupation ASC);
这样合并后的结果会先展示按姓名排序的格式化列表,再展示按次数升序的职业统计,两部分各自的排序都能完美保留。
内容的提问来源于stack exchange,提问作者Artur Ferfecki
相关产品推荐
相关产品推荐

