2009-08-20 4 views
3

J'ai une instruction SELECT similaire à celle ci-dessous qui renvoie plusieurs comptes dans une requête.Ajout de pourcentages à plusieurs comptes dans une requête SQL SELECT

SELECT invalidCount = (SELECT COUNT(*) FROM <...a...> WHERE <...b...>), 
     unknownCount = (SELECT COUNT(*) FROM <...c...> WHERE <...d...>), 
     totalCount = (SELECT COUNT(*) FROM <...e...> WHERE <...f...>) 

Cela fonctionne bien, mais je voulais ajouter deux colonnes de pourcentage au SELECT:

invalidCount * 100/totalCount AS PercentageInvalid, 
unknownCount * 100/totalCount AS UnknownPercentage 

Comment puis-je modifier mon instruction SELECT pour gérer cette situation?

Répondre

4

Vous pouvez utiliser une sous-requête dans la clause from:

select 
    s.invalidCount, 
    s.unknownCount, 
    s.totalCount, 
    invalidCount * 100/s.totalCount as PercentageInvalid, 
    unknownCount * 100/s.totalCount as PercentageUnknown 
from 
    (select invalidCount = (SELECT COUNT(*) FROM <...a...> WHERE <...b...>), 
     unknownCount = (SELECT COUNT(*) FROM <...c...> WHERE <...d...>), 
     totalCount  = (SELECT COUNT(*) FROM <...e...> WHERE <...f...>)) s 
0
SELECT invalidCount = (SELECT COUNT(*) FROM <...a...> WHERE <...b...>), 
     unknownCount = (SELECT COUNT(*) FROM <...c...> WHERE <...d...>), 
     totalCount  = (SELECT COUNT(*) FROM <...e...> WHERE <...f...>) 
INTO #tmp 

SELECT invalidCount, 
     unknownCount, 
     totalCount, 
     invalidCount * 100/totalCount AS PercentageInvalid, 
     unknownCount * 100/totalCount AS UnknownPercentage 
FROM #tmp 

DROP TABLE #tmp 
+0

est ce plus rapide que si vous faites « sélectionner invalidCount * 100 (etc.) de (requête existante) » – user158017

+0

Il ne suis pas sûr sorcière est plus rapide mais vous peut toujours écrire à la fois querys et exécuter le et voir witch est plus rapide en utilisant SQL Profiler – IordanTanev

3
SELECT invalidCount, 
    unknownCount, 
    totalCount, 
    invalidCount * 100/totalCount AS PercentageInvalid, 
    unknownCount * 100/totalCount AS UnknownPercentage 
FROM 
    (
     SELECT invalidCount = (SELECT COUNT(*) FROM <...a...> WHERE <...b...>), 
     unknownCount = (SELECT COUNT(*) FROM <...c...> WHERE <...d...>),  
     totalCount  = (SELECT COUNT(*) FROM <...e...> WHERE <...f...>) 
    ) 
+0

Ne pas oublier de CAST (totalCount comme flottant) - sinon vous faites la division entière ... –

+2

Cela ne fonctionnera pas, vous devez alias la sous-requête. – Eric

1

est ici une approche différente en utilisant la clause OVER qui est très cool - très efficace. Découvrez cet exemple contre AdventureWorks:

SELECT DISTINCT CardType 
     ,COUNT(*) OVER (PARTITION BY CardType) AS TypeCount 
     ,COUNT(*) OVER (PARTITION BY 1) AS TotalCount 
     ,COUNT(*) OVER (PARTITION BY CardType)/CAST(COUNT(*) OVER (PARTITION BY 1) AS float) AS TypePercent 
FROM Sales.CreditCard 
1

Je choisirais certainement la solution de Mike! Beaucoup plus élégant et plus efficace.

Mais je ne vois aucune raison de ne pas utiliser GROUP BY ici. Cela le rendrait encore plus élégant et plus efficace. Je suggérerais de se débarrasser d'un «COUNT (*) OVER (PARTITION BY 1)» redondant, et de faire la somme des comptes à la place.

SELECT CardType 
     , COUNT(*) AS TypeCount 
     , SUM(COUNT(*)) OVER() AS TotalCount 
     , COUNT(*) * 1.0/SUM(COUNT(*)) OVER() AS TypePercent 
FROM Sales.CreditCard 
GROUP BY CardType 

Notes:

  • "PARTITION BY 1" était redondant, donc omis. En prenant SUM de CardType-Counts, on enregistre à nouveau de compter la table entière une fois de nouveau sans partitionnement.
  • * 1,0 est utilisé à la place de la coulée.
  • la requête n'a pas été testé, mais il devrait fonctionner ..
Questions connexes