GROUP BY 子句

最近更新时间:2026-05-06 16:28:13

我的收藏
GROUP BY 子句用于将结果集划分为多个逻辑组,并对每个组执行聚合计算(如 COUNT()SUM()AVG()MIN()MAX())。

核心规则

非聚合列强制分组:SELECT 列表中出现的、未参与聚合计算的所有列名,必须全部列在 GROUP BY 子句中。
空值处理:TCHouse-X 对数据的区分度极高。在分组逻辑中,零长度字符串 ("")、NULL 和 空格 (" ") 被视为三个完全不同的独立值。

使用数字序号 GROUP BY

TCHouse-X 支持通过正整数来引用 SELECT 列表中的列位置,从而简化代码。
对应关系:正整数表示 SELECT 输出列表中的列序号(从 1 开始),而非原始物理表的列序号。这与 MySQL、PostgreSQL 和 Doris 的行为保持一致。
截断规则:如果使用小数(如 1.1),系统会将其截断为整数(1)处理。
不支持负数:使用 -1 等负数会导致错误。
示例
-- 以下两者等价
SELECT category, COUNT(*) FROM t1 GROUP BY category;
SELECT category, COUNT(*) FROM t1 GROUP BY 1;

-- 小数会被截断为整数
SELECT category, COUNT(*) AS cnt FROM t1 GROUP BY 1.1; -- 等价于 GROUP BY 1

-- 负数不支持
SELECT category, COUNT(*) FROM t1 GROUP BY -1;
-- Error: Expression 'CATEGORY' is not being grouped

浮点数分组的风险提示

在处理科学或金融数据时,需特别注意 FLOATDOUBLE 类型的列。
精度不确定性:由于硬件浮点数的存储特性,它们无法精确表示所有十进制分数(例如 96.94 在底层可能存储为 96.940002441...)。
分组结果偏差:当对浮点数列进行 GROUP BY 时,查询结果可能会因为这种微小的精度偏差产生“看似重复但值略有不同”的行。
解决方案:
1. 使用 ROUND() 函数对列进行四舍五入后再分组。
2. 使用 DECIMAL 类型存储货币或需要高精度的金融数据,以避免舍入误差。

综合案例

基础聚合与排序

查找销售总数量前 5 的商品及其销售次数:
SELECT
ss_item_sk AS Item,
COUNT(ss_item_sk) AS Times_Purchased,
SUM(ss_quantity) AS Total_Quantity
FROM store_sales
GROUP BY ss_item_sk
ORDER BY Total_Quantity DESC
LIMIT 5;

配合 HAVING 进行结果过滤

WHERE 无法过滤聚合后的结果,必须使用 HAVING。以下查询查找销售次数 >= 100 且销售总量最低的 5 个商品:
SELECT
ss_item_sk AS Item,
COUNT(ss_item_sk) AS Times_Purchased,
SUM(ss_quantity) AS Total_Quantity
FROM store_sales
GROUP BY ss_item_sk
HAVING Times_Purchased >= 100
ORDER BY Total_Quantity ASC
LIMIT 5;

常见问题 (FAQ)

可以在 GROUP BY 中使用别名吗?

是的,TCHouse-X 支持在 GROUP BY 中引用 SELECT 列表中定义的别名。

为什么我的分组结果比预期多?

请检查数据中是否存在不可见的空格或空值。如前文所述,TCHouse-X 会将它们视为不同的组。