SQL数据发生顺序混乱的情况的解决方法

date
Jul 12, 2023
slug
2023-07-12
status
Published
tags
Bug解决
技术
数据库
summary
由于ORDER BY变量缺少引起的数据顺序混乱的bug解决方案
type
Post

 
题目来自:https://www.nowcoder.com/share/jump/600110081689131772866
我目前遇到的是group by 以及order by引起的bug。
SELECT
	author,
	date_format(start_time, "%Y-%m") as month,
	round(sum(case when if_follow=1 then 1
	when if_follow=2 then -1
	else 0 end)/count(start_time), 3) as fans_growth_rate,
	sum(sum(case when if_follow=1 then 1
	when if_follow=2 then -1
	else 0 end)) OVER(partition by author ORDER BY DATE_FORMAT(start_time, "%Y-%m")) as total_fans
FROM tb_user_video_log a
LEFT JOIN tb_video_info b
	ON a.video_id=b.video_id
WHERE YEAR(start_time)=2021
GROUP BY author, month
ORDER BY author, total_fans
在一开始ORDER BY只有author,导致后面的数据混乱,比如两条数据的计算结果调换了。我猜测是ORDER的问题,查了下,看到 MySQL 的 order by 使用注意事项 中提到了这一点。
order by 和 group by 一起使用时,order by 后面的字段必须包含在聚合函数或者group by 子句中。
顺着去gpt问了下,得到了更加详细的解析:
当使用 GROUP BY 子句对数据进行分组时,每个分组将生成一个聚合值。这些聚合值是通过对每个分组中的数据进行聚合计算得出的,例如 SUM()、COUNT()、AVG() 等。 当您在使用 GROUP BY 子句时,ORDER BY 子句将影响分组后的结果集的顺序。如果您在 ORDER BY 子句中包含了未被聚合的列,则 SQL 引擎将需要决定如何处理这些列。具体来说,SQL 引擎需要选择一种方法来处理这些列的值,以便将它们包含在聚合函数或 GROUP BY 子句中。 有一种常见的方法是将这些列视为分组键,然后将它们添加到 GROUP BY 子句中。这样可以确保每个分组的数据都具有相同的值,并且可以正确计算聚合函数的值。例如,以下 SQL 查询将计算每个部门的平均工资,并按照部门名称进行排序:
SELECT department, AVG(salary) as avg_salary
FROM employees
GROUP BY department
ORDER BY department;
在这个查询中,ORDER BY 子句中的 department 列也出现在 GROUP BY 子句中,因为它是一个分组键。如果您省略了 GROUP BY 子句中的 department 列,则 SQL 引擎将无法确定每个部门的平均工资,并且会返回错误。 总之,为了正确处理 GROUP BY 和 ORDER BY 子句的组合,您需要确保 ORDER BY 子句中的列要么是聚合函数的参数,要么包含在 GROUP BY 子句中作为分组键。这可以确保每个分组的数据都具有相同的值,并且可以正确计算聚合函数的值。
总结是:ORDER中得有GROUP和除了GROUP以外的变量,才能保证顺序一致。

© chz8bit 2018 - 2024