DBAtlas · Atlas de operaciones de bases de datos

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 agrupa las filas por las columnas indicadas y aplica funciones de agregación; HAVING filtra el resultado agrupado (WHERE filtra las filas antes de agrupar). ROLLUP genera subtotales jerárquicos + un total general, CUBE todas las combinaciones y GROUPING SETS las agrupaciones seleccionadas. Oracle admite las tres.

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+ admite ROLLUP, CUBE y GROUPING SETS conforme al estándar. La función GROUPING() indica si una columna está en una fila de total (NULL). HAVING filtra después de la agregación y WHERE antes.

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 generan subtotales/totales generales con la sintaxis GROUP BY ... WITH ROLLUP; CUBE y GROUPING SETS no están soportados. Los alias de SELECT se pueden usar en HAVING (esto en general no funciona en Oracle/SQL Server). En las filas de ROLLUP, la columna agrupada aparece como 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);

Junto con GROUP BY, SQL Server admite ROLLUP(), CUBE() y GROUPING SETS (2008+) con sintaxis moderna; la antigua forma WITH ROLLUP/WITH CUBE está obsoleta. GROUPING() y GROUPING_ID() ayudan a distinguir las filas de total.

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

En MongoDB, $group es el equivalente de GROUP BY en SQL; _id establece la clave de agrupación y los acumuladores ($sum, $avg, $max) definen los agregados. El filtrado posterior a la agrupación se hace con $match (el equivalente de HAVING). Los totales de varios niveles como ROLLUP/CUBE se obtienen ejecutando varios pipelines con $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 básico no ofrece agrupación; el comando FT.AGGREGATE del módulo RediSearch realiza agregaciones tipo SQL con GROUPBY y REDUCE (COUNT, SUM, AVG). El paso FILTER filtra el resultado agrupado como HAVING. Sin el módulo, la agregación se hace en la aplicación.

Elasticsearch

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

En Elasticsearch, la agrupación se hace con la bucket aggregation 'terms' y los agregados con metric aggregations (sum, avg, cardinality). Para un filtrado tipo HAVING, use la pipeline aggregation 'bucket_selector'. Los subtotales de varios niveles se construyen con agregaciones anidadas.

Abrir en DBAtlas →