2010-06-21 4 views
1

J'ai plusieurs résultats de la requête qui utilisent une ou plusieurs fonctions globales et une date GROUP-BY afin qu'ils ressemblent à ceci:requête SQL qui applique la fonction globale sur une autre fonction d'agrégation

 
Date  VisitCount(COUNT) TotalBilling(SUM) 
1/1/10  234    15765.21 
1/2/10  321    23146.27 
1/3/10  289    19436.51 

Le SQL simplifié pour la ci-dessus est:

SELECT 
    VisitDate, 
    COUNT(*) AS VisitCount, 
    SUM(BilledAmount) AS TotalBilling 

FROM Visits 

GROUP BY VisitDate 

ce que je voudrais est un moyen d'appliquer une fonction d'agrégation, comme AVG à l'une des colonnes dans le jeu de résultats. Par exemple, je voudrais ajouter « AvgVisits » et colonnes « AvgBilling » au jeu de résultats comme celui-ci:

 
Date  VisitCount(COUNT) TotalBilling(SUM) AvgVisits AvgBilling 
1/1/10  234    15765.21   281.3  19449.33 
1/2/10  321    23146.27   281.3  19449.33 
1/3/10  289    19436.51   281.3  19449.33 

SQL ne permet pas l'application d'une fonction d'agrégation à une autre fonction d'agrégation ou une sous-requête, de sorte que le Je ne peux penser à cela qu'en utilisant une table temporaire ou en itérant dans le jeu de résultats et en calculant manuellement les valeurs. Est-ce que je peux faire ceci dans MSSQL2008 sans une table temporaire ou un calcul manuel?

+1

Je ne pense pas que cela n'a aucun sens sans une table temporaire. Vous devrez faire la requête deux fois: une fois pour calculer ces agrégats de toutes les colonnes, et ensuite pour vider une table avec les agrégats ajoutés à la fin. Je veux dire, vous ne pouvez pas calculer ces agrégats sans voir chaque ligne de la première table ... – Pointy

Répondre

5
with cteGrouped as (
SELECT 
    VisitDate, 
    COUNT(*) AS VisitCount, 
    SUM(BilledAmount) AS TotalBilling 
FROM Visits 
GROUP BY VisitDate), 
cteTotal as ( 
SELECT COUNT(*)/COUNT(DISTINCT VisitDate) as AvgVisits, 
    SUM(BilledAmount)/COUNT(DISTINCT VisitDate) as AvgBilling 
FROM Visits) 
SELECT * 
FROM cteGrouped 
CROSS JOIN cteTotal; 

Vous pouvez obtenir la même chose avec des sous-requêtes, je trouve juste que les CTE sont plus expressifs.

+0

Cela fait exactement ce dont j'ai besoin. Je vous remercie. – Dan

0

Eh bien, si vous essayez spécifiquement d'éviter d'utiliser des tables temporaires, je crois que cela pourrait être fait en utilisant un Common Table Expression.

1

quelque chose de similaire à

select *,avg(visitcount) over(), 
avg(totalbilling) over() 
from(
SELECT 
    VisitDate, 
    COUNT(*) AS VisitCount, 
    SUM(BilledAmount) AS TotalBilling 

FROM Visits 
GROUP BY VisitDate) as a