2010-06-21 2 views
1

У меня есть несколько результатов запросов, которые используют один или несколько агрегатных функции и дату GROUP-BY, чтобы они выглядели примерно так:SQL запрос, который применяет агрегатную функцию над другой агрегатной функцией

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

Упрощенный SQL для выше:

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

FROM Visits 

GROUP BY VisitDate 

То, что я хотел бы способ применить агрегатную функцию, например, AVG к одному из столбцов в наборе результатов. Например, я хотел бы добавить «AvgVisits» и столбцы «AvgBilling» в наборе результатов, как это:

 
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 не допускает применение агрегатной функции к другой функции совокупного или подзапроса, поэтому только способы, которые я могу сделать, это использовать временную таблицу или путем итерации через результирующий набор и вручную вычисления значений. Есть ли способ, которым я могу это сделать в MSSQL2008 без таблицы временных или ручных вычислений?

+1

Я не думаю, что это имеет смысл без временной таблицы. Вам нужно будет выполнить запрос дважды: один раз для вычисления этих агрегатов всех столбцов, а затем снова для выгрузки таблицы с добавленными в конец агрегатами. Я имею в виду, вы не можете вычислить эти агрегаты, не видя каждой строки первой таблицы ... – Pointy

ответ

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; 

Вы можете добиться того же, что и подзапросы, я просто нахожу CTEs более выразительным.

+0

Это делает именно то, что мне нужно. Спасибо. – Dan

0

Хорошо, если вы специально пытаетесь избежать использования временных таблиц, я считаю, что это можно сделать с помощью Common Table Expression.

1

нечто похожее на

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

FROM Visits 
GROUP BY VisitDate) as a 
Смежные вопросы