it-swarm.com.de

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

Durchführen eines WITH ROLLUP Bei der Gruppierung nach mehreren Feldern gibt MySQL für jede Gruppe eine Rollup-Zeile sowie die Gesamtzusammenfassung zurück:

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?

7
yoshi
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);
3
RolandoMySQLDBA

Wenn Sie nur die Summe benötigen, ist es wahrscheinlich effizienter, eine union all - Abfrage 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, erzeugt WITH ROLLUP Viele Teilmengen, 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.

2
Lennart

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)
1
EoghanM

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;
0
SaintJokel

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), ())
0
Caius Jard