GROUP BY, HAVING, ROLLUP/CUBE/GROUPING SETS
Oracle
-- Basic grouping + HAVING
SELECT city, COUNT(*) AS n
FROM customer
GROUP BY city
HAVING COUNT(*) > 5;
-- Subtotals and grand total with ROLLUP
SELECT city, district, SUM(balance)
FROM customer
GROUP BY ROLLUP(city, district);GROUP BY는 지정한 컬럼으로 행을 그룹화하고 집계 함수를 적용한다. HAVING은 그룹화된 결과를 필터링한다(WHERE는 그룹화 전에 행을 필터링). ROLLUP은 계층적 소계 + 총계를, CUBE는 모든 조합을, GROUPING SETS는 선택한 그룹 조합을 생성한다. Oracle은 세 가지를 모두 지원한다.
PostgreSQL
SELECT city, district, SUM(balance)
FROM customer
GROUP BY GROUPING SETS ((city, district), (city), ());
-- CUBE produces all subset combinations
SELECT city, district, SUM(balance)
FROM customer
GROUP BY CUBE(city, district);PostgreSQL 9.5+는 ROLLUP, CUBE, GROUPING SETS를 표준에 맞게 지원한다. GROUPING() 함수는 컬럼이 합계 행(NULL)에 속하는지 알려 준다. HAVING은 집계 후에, WHERE는 집계 전에 필터링한다.
MySQL
SELECT city, COUNT(*) AS n
FROM customer
GROUP BY city
HAVING n > 5;
-- ROLLUP in MySQL:
SELECT city, district, SUM(balance)
FROM customer
GROUP BY city, district WITH ROLLUP;MySQL/MariaDB는 GROUP BY ... WITH ROLLUP 구문으로 소계/총계를 생성하며, CUBE와 GROUPING SETS는 지원하지 않는다. HAVING에서 SELECT 별칭을 사용할 수 있다(Oracle/SQL Server에서는 일반적으로 동작하지 않음). ROLLUP 행에서는 그룹화 컬럼이 NULL로 표시된다.
SQL Server
SELECT city, COUNT(*) AS n
FROM customer
GROUP BY city
HAVING COUNT(*) > 5;
-- ROLLUP / CUBE / GROUPING SETS
SELECT city, district, SUM(balance)
FROM customer
GROUP BY ROLLUP(city, district);SQL Server는 GROUP BY와 함께 최신 구문의 ROLLUP(), CUBE(), GROUPING SETS(2008+)를 지원하며, 기존 WITH ROLLUP/WITH CUBE 형식은 deprecated다. GROUPING()과 GROUPING_ID()는 합계 행을 구분하는 데 도움이 된다.
MongoDB
// Closest equivalent: $group + $sum
db.customer.aggregate([
{ $group: { _id: "$city", n: { $sum: 1 } } },
{ $match: { n: { $gt: 5 } } }
])
// $facet is used for ROLLUP-like multi-level totalsMongoDB에서 $group은 SQL GROUP BY에 해당한다. _id가 그룹화 키를, accumulator($sum, $avg, $max)가 집계를 정의한다. 그룹화 후 필터링은 $match(HAVING에 해당)로 수행한다. ROLLUP/CUBE 같은 다단계 합계는 $facet으로 여러 파이프라인을 실행해 얻는다.
Redis
# Not applicable: core Redis has no GROUP BY.
# Aggregation with RediSearch:
FT.AGGREGATE customer_idx "*" GROUPBY 1 @city REDUCE COUNT 0 AS n기본 Redis는 그룹화를 제공하지 않는다. RediSearch 모듈의 FT.AGGREGATE 명령이 GROUPBY와 REDUCE(COUNT, SUM, AVG)로 SQL과 유사한 집계를 수행한다. FILTER 단계는 HAVING처럼 그룹화된 결과를 필터링한다. 모듈이 없으면 애플리케이션에서 집계한다.
Elasticsearch
GET customer/_search
{
"size": 0,
"aggs": {
"by_city": { "terms": { "field": "city" },
"aggs": { "total": { "sum": { "field": "balance" } } } }
}
}Elasticsearch에서 그룹화는 'terms' bucket aggregation으로, 집계는 metric aggregation(sum, avg, cardinality)으로 수행한다. HAVING과 유사한 필터링에는 'bucket_selector' pipeline aggregation을 사용한다. 다단계 소계는 중첩 aggregation으로 구성한다.