web-dev-qa-db-fra.com

Comprendre les différences entre CUBE et ROLLUP

Mon travail m'a demandé de savoir "combien de factures sont écrites pour chaque date?"

J'étais un peu coincé et j'ai demandé l'aide de mon professeur. Elle m'a envoyé une requête qui répondrait à la question "Combien de poêles de chaque type et version ont été construits? Pour un défi mais pas de points en plus, incluez le nombre total de poêles."

Ce fut la requête qu'elle m'a envoyé:

SELECT STOVE.Type + STOVE.Version AS 'Type+Version'
, COUNT(*) AS 'The Count'
FROM STOVE
GROUP BY STOVE.Type + STOVE.Version WITH ROLLUP;

J'ai donc peaufiné cette requête jusqu'à ce qu'elle réponde à mes besoins. Voici ce que je suis venu avec:

SELECT InvoiceDt
, COUNT(InvoiceNbr) AS 'Number of Invoices' 
FROM INVOICE 
GROUP BY InvoiceDt WITH ROLLUP 
ORDER BY InvoiceDt ASC;

Et cela a donné les résultats suivants que je voulais.

Quoi qu'il en soit, j'ai décidé de lire la clause ROLLUP et j'ai commencé avec un article de Microsoft . Il a déclaré que la clause ROLLUP était similaire à la clause CUBE, mais qu'elle se distinguait de la clause CUBE de la manière suivante:

  1. CUBE génère un jeu de résultats qui affiche les agrégats de toutes les combinaisons de valeurs des colonnes sélectionnées.
  2. ROLLUP génère un jeu de résultats qui affiche les agrégats pour une hiérarchie de valeurs dans les colonnes sélectionnées.

J'ai donc décidé de remplacer ROLLUP dans ma requête par CUBE pour voir ce qui se passerait. Ils ont produit les mêmes résultats. Je suppose que c'est là que je deviens confus.

Il semble que si vous utilisez le type de requête que je suis ici, il n'y a pas de différence pratique entre les deux clauses. Est-ce correct? Ou est-ce que je ne comprends pas quelque chose? Lorsque j'avais fini de lire l'article de Microsoft, j'avais pensé que mes résultats auraient dû être différents avec la clause CUBE.

64
krebshack

Vous ne verrez aucune différence puisque vous n’enroulez qu’une seule colonne. Prenons un exemple où nous faisons

ROLLUP (YEAR, MONTH, DAY)

Avec un ROLLUP, il aura les sorties suivantes:

YEAR, MONTH, DAY
YEAR, MONTH
YEAR
()

Avec CUBE, il aura les éléments suivants:

YEAR, MONTH, DAY
YEAR, MONTH
YEAR, DAY
YEAR
MONTH, DAY
MONTH
DAY
()

CUBE contient essentiellement tous les scénarios de cumul possibles pour chaque nœud alors que ROLLUP gardera la hiérarchie intacte (pour ne pas ignorer MONTH et afficher YEAR/DAY, alors que CUBE )

C'est pourquoi vous n'avez pas vu de différence puisque vous n'aviez qu'une seule colonne à remonter.

J'espère que ça t'as aidé.

148
Derek Kromm

Nous pouvons comprendre la différence entre ROLLUP et CUBE avec un exemple simple. Considérons que nous avons un tableau qui contient les résultats du test trimestriel des étudiants. Dans certains cas, nous avons besoin de voir le total correspondant au trimestre et aux étudiants. Voici le tableau échantillon

SELECT * INTO #TEMP
FROM
(
    SELECT 'Quarter 1' PERIOD,'Amar' NAME ,97 MARKS
    UNION ALL
    SELECT 'Quarter 1','Ram',88 
    UNION ALL
    SELECT 'Quarter 1','Simi',76 
    UNION ALL
    SELECT 'Quarter 2','Amar',94 
    UNION ALL
    SELECT 'Quarter 2','Ram',82 
    UNION ALL
    SELECT 'Quarter 2','Simi',71 
    UNION ALL
    SELECT 'Quarter 3' ,'Amar',95 
    UNION ALL
    SELECT 'Quarter 3','Ram',83 
    UNION ALL
    SELECT 'Quarter 3','Simi',77
    UNION ALL
    SELECT 'Quarter 4' ,'Amar',91 
    UNION ALL
    SELECT 'Quarter 4','Ram',84 
    UNION ALL
    SELECT 'Quarter 4','Simi',79
)TAB

enter image description here

1. ROLLUP (Peut trouver le total correspondant à une colonne)

(a) Obtenez le score total de chaque élève dans tous les trimestres.

SELECT * FROM #TEMP
UNION ALL
SELECT PERIOD,NAME,SUM(MARKS) TOTAL
FROM #TEMP
GROUP BY NAME,PERIOD 
WITH ROLLUP
HAVING PERIOD IS NULL AND NAME IS NOT NULL 
// Having is used inorder to emit a row that is the total of all totals of each student

Voici le résultat de (a)

enter image description here

(b) Si vous avez besoin d'obtenir le score total de chaque trimestre

SELECT * FROM #TEMP
UNION ALL
SELECT PERIOD,NAME,SUM(MARKS) TOTAL
FROM #TEMP
GROUP BY PERIOD,NAME 
WITH ROLLUP
HAVING PERIOD IS NOT NULL AND NAME IS NULL

Voici le résultat de (b)

enter image description here

2. CUBE (Trouver le total pour le trimestre et les étudiants en un seul coup)

SELECT PERIOD,NAME,SUM(MARKS) TOTAL
FROM #TEMP
GROUP BY NAME,PERIOD 
WITH CUBE
HAVING PERIOD IS NOT NULL OR NAME IS NOT NULL

Voici le résultat de CUBE

enter image description here

Maintenant, vous vous demandez peut-être comment utiliser ROLLUP et CUBE en temps réel. Parfois, nous avons besoin d'un rapport dans lequel nous devons voir le total de chaque trimestre et le total de chaque élève en un seul coup. Voici un exemple

Je modifie légèrement la requête CUBE ci-dessus, car nous avons besoin du total pour les deux totaux.

SELECT CASE WHEN PERIOD IS NULL THEN 'TOTAL' ELSE PERIOD END PERIOD,
CASE WHEN NAME IS NULL THEN 'TOTAL' ELSE NAME END NAME,
SUM(MARKS) MARKS
INTO #TEMP2
FROM #TEMP
GROUP BY NAME,PERIOD 
WITH CUBE

DECLARE @cols NVARCHAR (MAX)

SELECT @cols = COALESCE (@cols + ',[' + PERIOD + ']', 
               '[' + PERIOD + ']')
               FROM    (SELECT DISTINCT PERIOD FROM #TEMP2) PV  
               ORDER BY PERIOD    


DECLARE @query NVARCHAR(MAX)
SET @query = 'SELECT * FROM 
             (
                 SELECT * FROM #TEMP2
             ) x
             PIVOT 
             (
                 SUM(MARKS)
                 FOR [PERIOD] IN (' + @cols + ')
            ) p;' 

EXEC SP_EXECUTESQL @query

Maintenant, vous obtiendrez le résultat suivant

enter image description here

75
Sarath Avanavu

En effet, vous ne regroupez qu'une colonne.

Ajouter Group by InvoiceDt, InvoiceCountry _ (ou quel que soit le champ qui vous donnera plus de données.

Avec Cube, vous obtiendrez une somme pour chaque InvoiceDt et vous obtiendrez une somme pour chaque InvoiceCountry.

6
JeffO

Vous pouvez trouver plus de détails sur GROUPING SET, CUBE, ROLL UP. TL; DR, ils développent simplement GROUP BY + UNION ALL de manière à obtenir l’agrégation :)

https://technet.Microsoft.com/en-us/library/bb510427 (v = sql.105) .aspx

1
o0omycomputero0o