2009-12-14 4 views
0

Supposons que vous ayez cette table:Combinant deux requêtes pivot T-SQL dans un

CREATE TABLE Records 
(
    RecordId  int IDENTITY(1,1) NOT NULL, 
    CreateDate  datetime   NOT NULL, 
    IsSpecial  bit    NOT NULL 
    CONSTRAINT PK_Records PRIMARY KEY(RecordId) 
) 

maintenant un rapport doit être créé lorsque les enregistrements totaux et le total des dossiers spéciaux sont ventilées par mois. Je peux utiliser ces deux requêtes séparément:

--  TOTAL RECORDS PER MONTH 
SELECT January, February, March, April, May, June, 
    July, August, September, October, November, December 
FROM (
    SELECT RecordId, DATENAME(MONTH, CreateDate) AS RecordMonth 
    FROM dbo.Records 
) AS SourceTable 
PIVOT (
    COUNT(RecordId) FOR RecordMonth IN (January, February, March, April, May, June, 
    July, August, September, October, November, December) 
) AS PivotTable; 

--  TOTAL SPECIAL RECORDS PER MONTH 
SELECT January, February, March, April, May, June, 
    July, August, September, October, November, December 
FROM (
    SELECT RecordId, DATENAME(MONTH, CreateDate) AS RecordMonth 
    FROM dbo.Records 
    WHERE IsSpecial = 1 
) AS SourceTable 
PIVOT (
    COUNT(RecordId) FOR RecordMonth IN (January, February, March, April, May, June, 
    July, August, September, October, November, December) 
) AS PivotTable; 

Les résultats pourraient ressembler à ceci:

    Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec 
total    0  0 2  2  1  0  0 1  2  1  2 4 
total special  0  0 1  0  1  0  0 0  0  0  0 2 

Est-il possible de combiner ces deux requêtes en une seule requête plus efficace?

+0

Combiner comment? Pouvez-vous donner un exemple de jeu de résultats? – JeffO

Répondre

3

je le ferais comme ceci:

SELECT 
    CASE SQ.total_type 
      WHEN 1 THEN 'total special' 
      WHEN 2 THEN 'total expensive' 
      ELSE 'total' 
    END AS total_type, 
    SUM(CASE WHEN MONTH(R.CreateDate) = 1 THEN 1 ELSE 0 END) AS January, 
    SUM(CASE WHEN MONTH(R.CreateDate) = 2 THEN 1 ELSE 0 END) AS February, 
    SUM(CASE WHEN MONTH(R.CreateDate) = 3 THEN 1 ELSE 0 END) AS March, 
    ... 
FROM 
    dbo.Records R 
INNER JOIN 
    (
      SELECT 0 AS total_type UNION ALL -- All 
      SELECT 1 UNION ALL     -- IsSpecial 
      SELECT 2       -- IsExpensive 
    ) AS SQ ON 
    (R.IsSpecial | (R.IsExpensive * 2)) & SQ.total_type = SQ.total_type 
GROUP BY 
    SQ.total_type 
ORDER BY 
    SQ.total_type DESC 
+0

Bon point. Ne pas utiliser PIVOT ... – gbn

+0

Ma requête est incorrecte atm si ... travailler sur un correctif –

+0

Ok, je pense que cela fonctionne correctement maintenant –

2

Vous ne pouvez avoir qu'un agrégat (COUNT(RecordId)) par pivot, il suffit donc de combiner en un jeu de résultats avec UNION ALL avec une colonne supplémentaire appropriée pour identifier chaque pivot.

Sinon, vous avez aucun moyen de distinguer les 2 différents agrégats dans le pivot

+0

J'aime utiliser les expressions de table communes pour ce faire. –

0

Merci pour la solution Tom, qui répond à ma question de pivot.

Dommage pour moi J'ai eu la mauvaise question. Pour mon problème, je me sens maintenant, il serait préférable d'utiliser une requête de regroupement simple comme ceci:

SELECT DATENAME(MONTH, CreateDate) AS Month, 
    COUNT(*) AS Total, 
    SUM(CASE 
     WHEN IsSpecial = 1 THEN 1 
     ELSE 0 
    END) AS TotalSpecial, 
    SUM(CASE 
     WHEN IsExpensive = 1 THEN 1 
     ELSE 0 
    END) AS TotalExpensive 
FROM Records 
GROUP BY DATENAME(MONTH, CreateDate); 

Ensuite, tout ce qui reste à faire est de tourner les résultats avant qu'ils ne soient présentés. Ravi de savoir hein?