2014-08-29 70 views
1

所有,SQL聚集過來,PARTITION

這是我的#2的第一篇文章,這樣下去容易...

我使用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)) 
+0

對於UserAverage,我認爲您需要「OVER(按月分區(StartDate))」和「OVER(按月分區(StartDate),UserId)分區」。然後擺脫集團。如果這不起作用,您可能必須使用子查詢或派生表獲取OrgAverage。 – 2014-08-29 16:33:10

+0

這是一個偉大的想法。實際上,我認爲這樣做很有效,但不幸的是,結果集一遍又一遍地顯示相同的OrgAverage和UserAverage,以及同一個月(一月)一遍又一遍地顯示相同的OrgAverage和UserAverage。 – Shane 2014-08-29 16:39:52

回答

1

要加入兩個查詢在此一併

+0

這工作得很好!謝謝! – Shane 2014-08-29 18:02:19

1

分區丟失子句:

  • 每用戶每月平均
  • 每月
  • 所有組織平均

如果您一次只返回一個用戶的數據,那麼我n線選擇可能會給你帶來快樂:

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 

注 - 使用上月的比較可能是緩慢的 - 你可能會更好具有CTE(公共表表達式)

1

我能得到它的使用做自我加入,可能有更好的方法。

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 
1
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; 
0

您可以用更少的代碼如下嘗試。

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] 
+0

這一次炸彈告訴我'訂單'附近的語法不正確。在2008年的分區工作中「排序」?我知道窗口功能在2012年和2014年得到了一些升級。 – Shane 2014-08-29 18:05:26

+0

您可以嘗試刪除順序...沒有問題 – 2014-08-29 18:06:24