GROUPING() în MySQL

Deosebește rândurile de subtotal create de WITH ROLLUP (1) de rândurile obișnuite (0).

Sintaxă
GROUPING(expresie [, expresie] ...)

Ce face GROUPING()

GROUP BY ... WITH ROLLUP adaugă rânduri de subtotal și de total general, în care coloanele grupate sunt NULL. Dacă datele conțin ele însele NULL-uri, nu se mai vede care rând este subtotal. GROUPING(coloana) returnează 1 doar pentru NULL-urile adăugate de ROLLUP.

Argumentele trebuie să fie exact expresiile din GROUP BY. Cu mai multe argumente, rezultatul este o mască de biți: GROUPING(a, b) = GROUPING(a) * 2 + GROUPING(b). Funcția poate apărea în SELECT, HAVING și ORDER BY.

Parametri

Parametru Descriere
expresie O expresie din GROUP BY.

Ce returnează

0 sau 1 (pentru mai multe argumente, un număr format din biții lor).

Exemple

Exemplele de pe această pagină pornesc de la datele de mai jos. Rulează mai întâi acest cod, apoi exemplul.

CREATE TABLE vanzari (
  oras VARCHAR(20),
  produs VARCHAR(20),
  suma INT
);

INSERT INTO vanzari VALUES
  ('Iași', 'Laptop', 3500),
  ('Iași', 'Mouse', 160),
  ('Cluj', 'Laptop', 7000),
  ('Cluj', 'Mouse', 80),
  ('Cluj', NULL, 300);

Exemplul 1: Subtotaluri recunoscute

În Cluj există o vânzare fără produs (NULL din date). GROUPING() o deosebește de rândul de subtotal.

SELECT oras, produs, SUM(suma) AS total,
       GROUPING(oras) AS g_oras, GROUPING(produs) AS g_produs
FROM vanzari
GROUP BY oras, produs WITH ROLLUP;

Rezultat

+-------+--------+-------+--------+----------+
| oras  | produs | total | g_oras | g_produs |
+-------+--------+-------+--------+----------+
| Cluj  | NULL   |   300 |      0 |        0 |
| Cluj  | Laptop |  7000 |      0 |        0 |
| Cluj  | Mouse  |    80 |      0 |        0 |
| Cluj  | NULL   |  7380 |      0 |        1 |
| Iași  | Laptop |  3500 |      0 |        0 |
| Iași  | Mouse  |   160 |      0 |        0 |
| Iași  | NULL   |  3660 |      0 |        1 |
| NULL  | NULL   | 11040 |      1 |        1 |
+-------+--------+-------+--------+----------+

Exemplul 2: Etichete pentru subtotaluri

SELECT IF(GROUPING(oras), 'Toate orașele', oras) AS localitate,
       IF(GROUPING(produs), 'Total oraș', IFNULL(produs, 'fără produs')) AS articol,
       SUM(suma) AS total
FROM vanzari
GROUP BY oras, produs WITH ROLLUP;

Rezultat

+----------------+---------------+-------+
| localitate     | articol       | total |
+----------------+---------------+-------+
| Cluj           | fără produs   |   300 |
| Cluj           | Laptop        |  7000 |
| Cluj           | Mouse         |    80 |
| Cluj           | Total oraș    |  7380 |
| Iași           | Laptop        |  3500 |
| Iași           | Mouse         |   160 |
| Iași           | Total oraș    |  3660 |
| Toate orașele  | Total oraș    | 11040 |
+----------------+---------------+-------+

Exemplul 3: Doar rândurile de subtotal

SELECT oras, SUM(suma) AS total, GROUPING(oras, produs) AS masca
FROM vanzari
GROUP BY oras, produs WITH ROLLUP
HAVING GROUPING(oras, produs) <> 0;

Rezultat

+-------+-------+-------+
| oras  | total | masca |
+-------+-------+-------+
| Cluj  |  7380 |     1 |
| Iași  |  3660 |     1 |
| NULL  | 11040 |     3 |
+-------+-------+-------+

Greșeli frecvente

  • Folosești IFNULL(oras, 'Total') pentru etichetele de subtotal. Și NULL-urile reale din date primesc eticheta; folosește GROUPING().
  • Dai ca argument poziția coloanei (GROUPING(1)). Argumentul trebuie să fie expresia din GROUP BY, nu un număr de poziție.

Comenzi înrudite

  • GROUP BY: Grupează rândurile cu aceeași valoare, ca să calculezi totaluri pentru fiecare grup.
  • SUM: Adună valorile dintr-o coloană numerică.
  • ANY_VALUE(): Permite o coloană negrupată într-o interogare cu GROUP BY, luând o valoare oarecare din grup.