web-dev-qa-db-fra.com

Quand utiliser GROUPING SETS, CUBE et ROLLUP

J'ai récemment appris sur GROUPING SETS, CUBE et ROLLUP pour définir plusieurs ensembles de regroupement dans SQL Server.

Ce que je demande, c'est dans quelles circonstances utilisons-nous ces fonctionnalités? Quels sont les avantages et les avantages de les utiliser?

SELECT shipperid, YEAR(shippeddate) AS shipyear, COUNT(*) AS numorders
FROM Sales.Orders
GROUP BY GROUPING SETS ( ( shipperid, YEAR(shippeddate) ), ( shipperid ), ( YEAR(shippeddate) ), ( ) );


SELECT shipperid, YEAR(shippeddate) AS shipyear, COUNT(*) AS numorders
FROM Sales.Orders
GROUP BY CUBE( shipperid, YEAR(shippeddate) );


SELECT shipcountry, shipregion, shipcity, COUNT(*) AS numorders
FROM Sales.Orders
GROUP BY ROLLUP( shipcountry, shipregion, shipcity );

Tout d'abord, pour ceux qui n'ont pas encore lu sur le sujet:

Cela étant dit, ne pensez pas à ces options de regroupement comme des moyens d'obtenir un ensemble de résultats. Ce sont des outils de performance .

Prenons ROLLUP comme exemple simple.

Je peux utiliser la requête suivante pour obtenir le nombre d'enregistrements pour chaque valeur de GrpCol.

SELECT   GrpCol, count(*) AS cnt
FROM     dbo.MyTable
GROUP BY GrpCol

Et je peux utiliser la requête suivante pour "résumer" sommairement le nombre de TOUS les enregistrements.

SELECT   NULL, count(*) AS cnt
FROM     dbo.MyTable

Et je pourrais UNION ALL les deux requêtes ci-dessus pour obtenir exactement les mêmes résultats que j'aurais pu obtenir si j'avais écrit la première requête avec la clause ROLLUP (c'est pourquoi j'ai mis le NULL dedans).

Il pourrait en fait être plus pratique pour moi d'exécuter cela en tant que deux requêtes différentes, car j'ai alors les résultats groupés séparés de mes totaux. Pourquoi voudrais-je que mon total final soit mélangé au reste de ces résultats? La réponse est que faire les deux ensemble en utilisant la clause ROLLUP est plus efficace. SQL Server utilise un plan d'exécution qui calcule toutes les agrégations ensemble en une seule passe. Comparez cela au UNION ALL exemple qui fournirait exactement les mêmes résultats mais utiliserait un plan d'exécution moins efficace (deux analyses de table au lieu d'une).

Imaginez un exemple extrême dans lequel vous travaillez sur un ensemble de données si volumineux que chaque analyse des données prend une heure entière. Vous devez fournir des totaux sur pratiquement toutes les dimensions possibles (façon de découper) ces données chaque jour. Aha! Je parie que l'une de ces options de regroupement est exactement ce dont vous avez besoin. Si vous enregistrez les résultats de cette analyse dans une disposition de schéma spéciale, vous pourrez alors exécuter des rapports pour le reste de la journée sur les résultats enregistrés.

Je dis donc essentiellement que vous travaillez sur un projet d'entrepôt de données. Pour le reste d'entre nous, il appartient principalement à la catégorie "chose intéressante à savoir".

25
SurroundedByFish

CUBE est identique à GROUPING SETS avec toutes les combinaisons possibles.

Donc ceci (en utilisant CUBE)

GROUP BY CUBE (C1, C2, C3, ..., Cn-2, Cn-1, Cn)

est la même chose (en utilisant GROUPING SETS)

GROUP BY GROUPING SETS (
     (C1, C2, C3, ..., Cn-2, Cn-1, Cn) -- All dimensions are included.
    ,( , C2, C3, ..., Cn-2, Cn-1, Cn) -- n-1 dimensions are included.
    ,(C1, C3, ..., Cn-2, Cn-1, Cn)
    …
    ,(C1, C2, C3, ..., Cn-2, Cn-1,)
    ,(C3, ..., Cn-2, Cn-1, Cn) -- n-2 dimensions included
    ,(C1  ..., Cn-2, Cn-1, Cn)
    …
    ,(C1, C2) -- 2 dimensions are included.
    ,…
    ,(C1, Cn)
    ,…
    ,(Cn-1, Cn)
    ,…
    ,(C1) -- 1 dimension included
    ,(C2)
    ,…
    ,(Cn-1)
    ,(Cn)
    ,() ) -- Grand total, 0 dimension is included.

Ensuite, si vous n'avez pas vraiment besoin de toutes les combinaisons, vous devez utiliser GROUPING SETS plutôt que CUBE

Les opérateurs ROLLUP et CUBE génèrent certains des mêmes jeux de résultats et effectuent certains des mêmes calculs que les applications OLAP. L'opérateur CUBE génère un jeu de résultats qui peut être utilisé pour les rapports de tabulation croisée. Une opération ROLLUP peut calculer l'équivalent d'une dimension ou d'une hiérarchie OLAP.

Regardez ici pour voir les équivalents des ensembles de regroupement


[~ # ~] mise à jour [~ # ~]

Je pense qu'un exemple aiderait ici. Supposons que vous ayez un tableau du nombre d'observations d'OVNIS par pays et par sexe, comme ci-dessous:

╔═════════╦═══════╦═════════╗
║ COUNTRY ║ GENDER║ #SIGHTS ║
╠═════════╬═══════╬═════════╣
║ USA     ║ F     ║     450 ║
║ USA     ║ M     ║    1500 ║
║ ITALY   ║ F     ║     704 ║
║ ITALY   ║ M     ║     720 ║
║ SWEDEN  ║ F     ║     317 ║
║ SWEDEN  ║ M     ║     310 ║
║ BRAZIL  ║ F     ║     144 ║
║ BRAZIL  ║ M     ║     159 ║
╚═════════╩═══════╩═════════╝

Ensuite, si vous souhaitez connaître les totaux pour chaque pays, par sexe et grand total uniquement, vous devez utiliser GROUPING SETS

 select Country, Gender, sum(Number_Of_Sights)
 from Table1
 group by GROUPING SETS((Country), (Gender), ())
 order by Country, Gender

SQL Fiddle

Pour obtenir le même résultat avec GROUP BY, vous utiliseriez UNION ALL comme:

select Country, NULL Gender, sum(Number_Of_Sights)
from Table1
GROUP BY Country
UNION ALL
select NULL Country, Gender, sum(Number_Of_Sights)
from Table1
GROUP BY GENDER
UNION ALL
SELECT NULL Country, NULL Gender, sum(Number_Of_Sights)
FROM TABLE1
ORDER BY COUNTRY, GENDER

SQL Fiddle

Mais il n'est pas possible d'obtenir le même résultat avec CUBE, car il renverra toutes les possibilités.

Maintenant, si vous voulez connaître toutes les combinaisons possibles, vous devez utiliser CUBE

21
Nizam

Je trouve qu'ils sont bons lorsque vous produisez un rapport et que le résultat n'est pas quelque chose qui peut être cumulé au sein du client.

Par exemple, si vous faites quelque chose avec COUNT(DISTINCT...) alors le résultat sur un groupe plus large n'est pas nécessairement la même valeur que la somme des parties. Par exemple, sur deux jours individuels, vous pourriez avoir 1 500 visiteurs et 2 000 visiteurs, mais le total pourrait se situer entre 2 000 et 3 500, selon le chevauchement. C'est bien de le faire dans le client, mais parce que le client ne peut pas dire quel est le chevauchement, vous pouvez utiliser GROUPING SETS pour fournir la réponse (puis gérer cette ligne supplémentaire qui apparaît dans le rapport).

5
Rob Farley