Erhalten Sie nur eine Gesamtübersicht MIT ROLLUP und GROUP BY für mehrere Felder

7

Durchführen einer , WITH ROLLUPwenn es durch mehrere Felder Gruppierungs kehrt MySQL eine Aufsummierung Zeile für jede Gruppe, sowie die Gesamtübersicht:

CREATE TABLE test (name VARCHAR(50), number TINYINT);
INSERT INTO test VALUES
    ('foo', 1), ('foo', 1), ('foo', 2), ('foo', 3), ('foo', 3),
    ('bar', 1), ('bar', 2), ('bar', 2), ('bar', 2), ('bar', 3),
    ('baz', 1), ('baz', 2), ('bar', 2);
SELECT name, number, COUNT(1) FROM test GROUP BY name, number WITH ROLLUP;

+------+--------+----------+
| name | number | count(1) |
+------+--------+----------+
| bar  |      1 |        1 |
| bar  |      2 |        3 |
| bar  |      3 |        1 |
| bar  |   NULL |        5 |
| baz  |      1 |        1 |
| baz  |      2 |        2 |
| baz  |   NULL |        3 |
| foo  |      1 |        2 |
| foo  |      2 |        1 |
| foo  |      3 |        2 |
| foo  |   NULL |        5 |
| NULL |   NULL |       13 |
+------+--------+----------+

Ich bin nicht an den Rollups für foo / bar / baz interessiert, sondern nur an der Gesamtzusammenfassung. Was ist der effizienteste Weg, um dies zu erreichen?

Yoshi
quelle

Antworten:

3
SELECT * FROM
(
    SELECT name, number, COUNT(1) `count` FROM test
    GROUP BY name, number WITH ROLLUP
) A WHERE (ISNULL(name) + ISNULL(number)) <> 1;

oder

SELECT * FROM
(
    SELECT name, number, COUNT(1) `count` FROM test
    GROUP BY name, number WITH ROLLUP
) A WHERE ISNULL(name) = ISNULL(number);
RolandoMySQLDBA
quelle
2

Wenn Sie nur die Summe benötigen, ist es wahrscheinlich effizienter, eine union allAbfrage wie diese zu verwenden:

select name, number, count(1) 
from test 
group by name, number 
union all 
select null, null, count(1) 
from test;

Wenn Sie viele Attribute haben, WITH ROLLUPwerden viele Teilmengen erzeugt, die Sie einfach in der äußeren Auswahl wegwerfen. Ich glaube nicht, dass der MySQL-Optimierer erkennen wird, dass er diese überspringen kann, aber es ist nur eine Vermutung.

Lennart
quelle
1

Sie können auch versuchen, HAVING:

SELECT name, number, COUNT(1) 
FROM test GROUP BY name, number 
WITH ROLLUP 
HAVING (number is not null or name is null);

oder

HAVING (number is null) = (name is null)
EoghanM
quelle
0

Wenn Sie nur an der Gesamtzusammenfassung interessiert sind, sollten Sie einfach eine Abfrage schreiben, in der Sie danach gefragt werden:

SELECT null, null, count(*) FROM test

(Sie haben eine Testtabelle mit 13 Zeilen erstellt, die in jeder Spalte mit Rollup gruppiert wurde, und dann gesagt, dass Sie nur an der Zeile interessiert sind, die effektiv die Anzahl der Zeilen in der Tabelle zählt. Tun Sie das einfach.)

Wenn Sie nur an den Detailzeilen und der Gesamtzusammenfassung interessiert sind, sind Gruppierungssätze genau das Richtige für:

SELECT name, number, count(*) FROM test GROUP BY GROUPING SETS ((name, number), ())

Der leere Satz gibt die Zusammenfassung an, der Name + die Nummer geben die Details an. ROLLUP entspricht diesem Gruppierungssatz:

((name, number), (name), ())
Caius Jard
quelle
1
Schön, aber MySQL hat nicht GROUP BY GROUPING SETS.
Ypercubeᵀᴹ
0

In diesem Fall entspricht die Gesamtzusammenfassung der Anzahl der Datensätze (Häufigkeit).

SELECT count(1) FROM test;

Wenn Sie an der Gesamtübersicht der Zahlen interessiert sind, dann

SELECT SUM(numbers) FROM test;
SaintJokel
quelle