Modificadores GROUP BY
No MariaDB, a cláusula GROUP BY
permite um modificador WITH ROLLUP
que faz com que uma linha extra seja adicionada à saida resumo. Estas linhas representam operações de resumo de nível mais alto (ou super agregadas). Assim, o ROLLUP
permite que você responda questões em multiplos níveis de análise com uma única consulta. Ele pode ser usado, por exemplo, para fornecer suporte para operações OLAP (Online Analytical Processing - Processamento Analítico OnLine).
Como ilustração, suponha que uma tabela chamada sales
tenha as colunas year
, country
, product
e profit
para registrar as vendas lucrativas:
CREATE TABLE sales ( year INT NOT NULL, country VARCHAR(20) NOT NULL, product VARCHAR(32) NOT NULL, profit INT );
O conteúdo da tabela pode ser resumido pode ano com um simples GROUP BY
como este:
mysql> SELECT year, SUM(profit) FROM sales GROUP BY year;
+------+-------------+
| year | SUM(profit) |
+------+-------------+
| 2000 | 4525 |
| 2001 | 3010 |
+------+-------------+
Esta saída mostra o lucro total para cada ano, mas se você também quiser determinar o lucro total somado em todos os anos, você deve adicionar os valores adicionais ou executar uma consulta adicional.
Ou você pode usar o ROLLUP
, que fornece os dois níveis de análise com uma única consulta. Adicionando um modificador WITH ROLLUP
a cláusula GROUP BY
faz com que a consulta produza outra linha que mostra o total geral de todos os anos:
mysql> SELECT year, SUM(profit) FROM sales GROUP BY year WITH ROLLUP;
+------+-------------+
| year | SUM(profit) |
+------+-------------+
| 2000 | 4525 |
| 2001 | 3010 |
| NULL | 7535 |
+------+-------------+
A linha de total super-agrupada é identificada pelo valor NULL
na coluna year
.
ROLLUP
tem um efeito mais complexo quando há múltiplas colunas GROUP BY
. Neste caso, cada vez que houver um break
(alteração no valor) em qualquer agrupamento, com exceção da última coluna, a consulta produz um linha resumo super-agrupada extra.
Por exemplo, sem ROLLUP
, um resumo na tabela sales
baseada no year
, country
e product
pode se parecer com isto:
mysql>SELECT year, country, product, SUM(profit)
->FROM sales
-> GROUP BY year, country, product; +------+---------+------------+-------------+ | year | country | product | SUM(profit) | +------+---------+------------+-------------+ | 2000 | Finland | Computer | 1500 | | 2000 | Finland | Phone | 100 | | 2000 | India | Calculator | 150 | | 2000 | India | Computer | 1200 | | 2000 | USA | Calculator | 75 | | 2000 | USA | Computer | 1500 | | 2001 | Finland | Phone | 10 | | 2001 | USA | Calculator | 50 | | 2001 | USA | Computer | 2700 | | 2001 | USA | TV | 250 | +------+---------+------------+-------------+
A saída indica os valores resumidos apenas no nível year/country/product da análise. Quando ROLLUP
é adicionado, a consulta produz diversas linhas extras:
mysql>SELECT year, country, product, SUM(profit)
->FROM sales
->GROUP BY year, country, product WITH ROLLUP;
+------+---------+------------+-------------+ | year | country | product | SUM(profit) | +------+---------+------------+-------------+ | 2000 | Finland | Computer | 1500 | | 2000 | Finland | Phone | 100 | | 2000 | Finland | NULL | 1600 | | 2000 | India | Calculator | 150 | | 2000 | India | Computer | 1200 | | 2000 | India | NULL | 1350 | | 2000 | USA | Calculator | 75 | | 2000 | USA | Computer | 1500 | | 2000 | USA | NULL | 1575 | | 2000 | NULL | NULL | 4525 | | 2001 | Finland | Phone | 10 | | 2001 | Finland | NULL | 10 | | 2001 | USA | Calculator | 50 | | 2001 | USA | Computer | 2700 | | 2001 | USA | TV | 250 | | 2001 | USA | NULL | 3000 | | 2001 | NULL | NULL | 3010 | | NULL | NULL | NULL | 7535 | +------+---------+------------+-------------+
Para esta consulta, adicionar ROLLUP
faz com que a saída inclua uma informação resumida nos qualtro níveis de análise, não só em um. Aqui está como interpretar a saída ROLLUP
:
- Seguindo cada conjunto de produtos para um dado ano e país, um linha de resumo extra é produzida mostrando o total para todos os produtos. Estas linhas têm a coluna
product
atribuída comNULL
. - Seguindo cada conjunto de linhas para um dado ano, uma l;inha resumo extra é produzida mostrando o total para todos os países e produtos. Estas linhas têm as colunas
country
eproducts
atribuídas comNULL
. - Finalmente, seguindo todas as outras linhas, um linha resumo extra é produzida mostrando o total geral para todos os anos, países e produtos. Esta linha tem as colunas
year
,country
eproducts
atribuídas comNULL
.
Outras Considerações ao Usar ROLLUP
O seguinte item lista alguns comportamentos específicaos para a implementação do ROLLUP
no MySQL:
Quando você usa ROLLUP
, você não pode usar uma cláusula ORDER BY
para ordenar os resultados. (Em outras palavras, ROLLUP
e ORDER BY
são exclusivos mutualmente.) No entanto, você ainda tem algum controle sobre a ordem de ordenação. O GROUP BY
no MariaDB ordena os resultados, e você pode usar as palavras chaves ASC
e DESC
explicitamente com colunas chamadas na lista GROUP BY
para especificar a ordem de classificação para colunas individuais. (A linha resumo de nível mais alto adicionado por ROLLUP
ainda aparece depois da linha para as quais elas são calculadas, considerando a ordenação.)
LIMIT
pode ser usado para restringir o númerod e linhas retornadas para o cliente. LIMIT
é aplicado depois do ROLLUP
, assim o limite se aplica contra as linhas extras adicionadas por ROLLUP
. Por exemplo:
mysql>SELECT year, country, product, SUM(profit)
->FROM sales
->GROUP BY year, country, product WITH ROLLUP
->LIMIT 5;
+------+---------+------------+-------------+ | year | country | product | SUM(profit) | +------+---------+------------+-------------+ | 2000 | Finland | Computer | 1500 | | 2000 | Finland | Phone | 100 | | 2000 | Finland | NULL | 1600 | | 2000 | India | Calculator | 150 | | 2000 | India | Computer | 1200 | +------+---------+------------+-------------+
Note que usar LIMIT
com ROLLUP
pode produzir resultados mais difíceis de interpretar, porque você têm menos contexto para entender as linhas super agrupadas.
O indicador NULL
em cada linha super-agrupadas são produzidas quando a linha é enviada para o cliente. O servidor olha por cada coluna chamada na cláusula GROUP BY
seguindo aquela mais a esquerda que tem o valor alterado. Para qualquer coluna no resultado com o nome que é uma combinação léxica de qualquer daqueles nomes, seu valor é definido com NULL
. (Se você especifica o agrupamento de colunas pelo número da coluna, o servidor identifica quais colunas definir com NULL
pelo número.)
Como os valores NULL
em linhas super agrupadas são colocadas dentro do resultado como um estágio posterior no processamento da consulta, você não pode testá-los com valores NULL
dentro da própria consulta. Por exemplo, você não pode adicionar HAVING product IS NULL
a consulta para eliminar da saída todas as linhas com exceção das agrupadas.
Por outro lado, o valor NULL
aparece como NULL
no lado do cliente e pode ser testado usando qualquer interface de programação do cliente MySQL.