[英]SQL Aggregates OVER and PARTITION
所有,
这是我关于Stackoverflow的第一篇文章,所以轻松吧...
我正在使用SQL Server 2008。
我刚开始编写SQL查询,但遇到一个我认为很简单的问题,但是我已经奋斗了2天。 我有一组看起来像这样的数据:
UserId Duration(Seconds) Month
1 45 January
1 90 January
1 50 February
1 42 February
2 80 January
2 110 February
3 45 January
3 62 January
3 56 January
3 60 February
现在,我要编写一个查询,为我提供特定用户的平均值,并将其与该月所有用户的平均值进行比较。 因此,查询用户#1后的结果数据集将如下所示:
UserId Duration(seconds) OrganizationDuration(Seconds) Month
1 67.5 63 January
1 46 65.5 February
我一直在围绕不同的子查询和按场景分组,似乎没有任何工作。 最近,我一直在尝试OVER和PARTITION BY,但也没有成功。 我最新的查询如下所示:
select Userid,
AVG(duration) OVER () as OrgAverage,
AVG(duration) as UserAverage,
DATENAME(mm,MONTH(StartDate)) as Month
from table.name
where YEAR(StartDate)=2014
AND userid=119
GROUP BY MONTH(StartDate), UserId
该查询在选择列表中用“持续时间”轰炸,因为它没有包含在聚合函数或GROUP BY子句中,因此无效。
请记住,我正在处理大量数据。 我认为我可以使其与CASE语句一起使用,但是我正在寻找一种更简洁,更有效的方式来编写查询(如果可能)。
谢谢!
平均函数中缺少分区子句
OVER ( Partition by MONTH(StartDate))
您在这里将两个查询结合在一起:
如果您一次仅要返回一个用户的数据,那么内联选择可能会给您带来欢乐:
SELECT AVG(a.duration) AS UserAvergage,
(SELECT AVG(b.Duration) FROM tbl b WHERE MONTH(b.StartDate) = MONTH(a.StartDate)) AS OrgAverage
...
FROM tbl a
WHERE userid = 119
GROUP BY MONTH(StartDate), UserId
注意-在MONTH上使用比较可能会比较慢-使用CTE(通用表表达式)可能会更好
我能够通过自我连接完成它,这可能是一种更好的方法。
Select UserId, AVG(t1.Duration) as Duration, t2.duration as OrgDur, t1.Month
from #temp t1
inner join (Select Distinct MONTH, AVG(Duration) over (partition by Month) as duration
from #temp) t2 on t2.Month = t1.Month
group by t1.Month, t1.UserId, t2.Duration
order by t1.UserId, Month desc
这里使用的CTE可能是更好的解决方案,而且绝对更易于阅读
With MonthlyAverage
as
(
Select MONTH, AVG(Duration) as OrgDur
from #temp
group by Month
)
Select UserId, AVG(t1.Duration) as Duration, m.duration as OrgDur , t1.Month
from #temp t1
inner join MonthlyAverage m on m.Month = t1.Month
group by UserId, t1.Month, m.duration
Please try this. It works fine to me.
WITH C1
AS
(
SELECT
AVG(Duration) AS TotalAvg,
[Month]
FROM [dbo].[Test]
GROUP BY [Month]
),
C2
AS
(
SELECT Distinct UserID,
AVG(Duration) OVER(PARTITION BY UserID, [Month] ORDER BY UserID) AS DetailedAvg,
[Month]
FROM [dbo].[Test]
)
SELECT C2.*, C1.TotalAvg
FROM C2 c2
INNER JOIN C1 c1 ON c1.[Month] = c2.[Month]
ORDER BY c2.UserID, c2.[Month] desc;
您可以在下面用更少的代码尝试。
SELECT Distinct UserID,
AVG(Duration) OVER(PARTITION BY [Month]) AS TotalAvg,
AVG(Duration) OVER(PARTITION BY UserID, [Month] ORDER BY UserID) AS DetailedAvg,
[Month]
FROM [dbo].[Test]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.