DBAtlas · Атлас эксплуатации баз данных

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 не поддерживаются. Псевдонимы SELECT можно использовать в HAVING (в 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);

Наряду с GROUP BY SQL Server поддерживает ROLLUP(), CUBE() и GROUPING SETS (2008+) в современном синтаксисе; старая форма WITH ROLLUP/WITH CUBE устарела. 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 totals

В MongoDB $group — эквивалент SQL GROUP BY; _id задаёт ключ группировки, а аккумуляторы ($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 не предлагает группировки; команда FT.AGGREGATE модуля RediSearch выполняет агрегацию в стиле SQL через GROUPBY и REDUCE (COUNT, SUM, AVG). Шаг FILTER фильтрует сгруппированный результат, как HAVING. Без модуля агрегация выполняется в приложении.

Elasticsearch

GET customer/_search
{
  "size": 0,
  "aggs": {
    "by_city": { "terms": { "field": "city" },
      "aggs": { "total": { "sum": { "field": "balance" } } } }
  }
}

В Elasticsearch группировка выполняется bucket-агрегацией 'terms', а агрегаты — метрическими агрегациями (sum, avg, cardinality). Для фильтрации в стиле HAVING используйте pipeline-агрегацию 'bucket_selector'. Многоуровневые промежуточные итоги строятся вложенными агрегациями.

Открыть в DBAtlas →