编程数据分析师 / 后端开发者

在SQL中使用GROUP BY结构时,特别是在聚合和优化复杂查询时,有哪些潜在问题?

用 Hintsage AI 助手通过面试

答案。

GROUP BY用于对行进行分组和聚合数据,但如果使用不当,可能会导致严重的错误或不优化的性能。

关键细节:

  • 在SELECT中只允许出现GROUP BY中的列或聚合函数。
  • 在包含多个JOIN的复杂查询中,可能会出现重复和错误的聚合。
  • 正确的顺序:GROUP BY在WHERE之后,HAVING之前执行。
  • 如果集团列没有索引,查询在大数据集上可能会非常慢。
  • HAVING是在分组后进行过滤,而WHERE是在分组前进行。

示例:

SELECT customer_id, COUNT(*) as orders FROM orders WHERE order_date >= '2024-01-01' GROUP BY customer_id HAVING COUNT(*) > 10;

误导性的问题。

在GROUP BY后,是否可以在SELECT中引用未在GROUP BY或聚合函数中指定的字段?

**答案:**不可以,这将在大多数SQL实现中导致错误(例如,在MS SQL、PostgreSQL中)。一些特定的数据库可能会返回偶然的不正确值(特别是在MySQL中,当sql_mode 'ONLY_FULL_GROUP_BY'关闭时),但这种行为是不正确的,并且不受标准保证。正确的示例:

SELECT department, AVG(salary) FROM employees GROUP BY department;

由于对该主题细微差别缺乏了解而导致的真实错误示例。


故事

在电子商务项目中,报表“按商品收入”通过查询SELECT sku, price, SUM(qty) FROM orders GROUP BY sku进行准备。 忽略了:price没有出现在GROUP BY中,并且不在聚合函数内,结果是MySQL返回了第一个找到的价格值,这在促销期间导致报告出现严重错误。修复方式是将price添加到GROUP BY中,或使用聚合函数。


故事

在BI项目中,复杂的报告执行了80分钟,而计划只需3分钟。 经过分析发现:GROUP BY和过滤字段缺少索引,创建了巨大的临时表进行聚合。解决方案是优化索引并重写查询,以使用表表达式。


故事

开发人员使用HAVING过滤未聚合的用户属性值。 结果服务器处理了所有数据的分组,然后通过HAVING进行了删除,降低了性能。修复方案是将该检查移至WHERE,以便在聚合之前缩小选择。