SELECT group_col, aggregate_func(col)
FROM table
WHERE filter_condition
GROUP BY group_col
HAVING group_condition
ORDER BY sort_col;
GROUP BY 子句中。COUNT/SUM/AVG/MIN/MAX/GROUP_CONCAT 等。WHERE 在分組前過濾行,HAVING 在分組後過濾組。保留 WHERE 過濾掉的分組,聚合值以 NULL/0 填充。MySQL 需用 LEFT JOIN 模擬。
SELECT dept_id, sex, COUNT(*) AS cnt
FROM employee
GROUP BY dept_id, sex WITH ROLLUP;
結果包含:
1. 明細行(dept+sex)
2. 部門小計(sex=NULL)
3. 總計(dept=NULL, sex=NULL)
SELECT dept_id, sex, COUNT(*) AS cnt,
GROUPING(dept_id) AS g_dept,
GROUPING(sex) AS g_sex
FROM employee
GROUP BY dept_id, sex WITH ROLLUP;
GROUPING(col)=1 表示該行為該欄位的小計行(NULL 由 ROLLUP 產生)。HAVING GROUPING(sex)=1 只取小計。產生所有欄位組合的小計。MySQL 可用多個 GROUPING SETS(8.0+)或 UNION ALL 模擬。
SELECT dept_id, sex, COUNT(*)
FROM employee
GROUP BY GROUPING SETS ((dept_id, sex), (dept_id), (sex), ());
等同 CUBE,但可精確控制組合。
含義:WHERE 不能用聚合函數/別名;HAVING 可用聚合函數;ORDER BY 可用別名。
SELECT COUNT(*) AS product_count, discount,
GROUPING(discount) AS is_subtotal
FROM fruit
GROUP BY discount WITH ROLLUP;
結果:
3 | NULL | 0(無折扣組)
1 | 0.8 | 0
1 | 0.9 | 0
1 | 1.0 | 0
6 | NULL | 1(總計行,GROUPING=1 識別)