2016-04-15 100 views
0

我有以下查詢:SQL服務器HAVING COUNT OVER問題

SELECT DISTINCT 
    x.CountryID [code], 
    c.Description [name], 
    COUNT(x.username) OVER(PARTITION BY x.countryID) [count], 
    COUNT(x.username) OVER() [tcount], 
    COALESCE(c.Map,'world') [map] 
FROM 
(
    SELECT DISTINCT 
     CountryID, 
     username, 
     Score 
    FROM global.dbo.UserCategories 
    WHERE TLCID LIKE @TLCID OR TLCID IN (@TLCID) 
) x 
JOIN global.dbo.countrydetails c on x.CountryID=c.country 
AND x.Score BETWEEN @ScoreMin AND @ScoreMax 
GROUP BY x.CountryID, c.Description, c.Map, x.username --WITH ROLLUP 
--HAVING COUNT(x.username) OVER(PARTITION BY x.countryID)>@Min 
ORDER BY [name] ASC 

,顯示了每個國家有某些類別 了一定的成績和活躍用戶的數量,我想從列表中國家排除有幾個用戶 ,我想補充HAVING子句 但SQL告訴我

「窗函數只能出現在SELECT或ORDER BY子句 。」

最重要的表是CountryDetails看起來像這樣:有關結果

CountryID username score  TLCID 
    DE  12-bu  19598  131090 
    DE  12-bu  19598  220 
    DE  12-bu  19598  11700 
    DE  12-bu  19598  131090 
    DE  1buy3  19648  11700 
    DE  1buy3  19648  11450 
    DE  1buy3  19648  11700 
    DE  1buy3  19648  11700 
    CN  2012f  22780  11450 
    CN  2012f  22780  11450 
    CN  2012f  22780  11450 
    CN  2012f  22780  11450 
    CN  2012f  22780  11450 
    GB  agood  74539  1 
    GB  agood  74539  11450 
    GB  agood  74539  12576 
    GB  agood  74539  131090 
    GB  agood  74539  1 
    GB  agood  74539  11233 
    GB  agood  74539  1 
    GB  agood  74539  1 
    GB  agood  74539  1 
    GB  agood  74539  220 
    BG  best0  3173  2984 
    IT  bestb  13777  15032 
    IT  bestb  13777  293 
    IT  bestb  13777  293 
    IT  bestb  13777  15032 
    IT  bestb  13777  15032 
    IT  bestb  13777  15032 
    IT  bestb  13777  58058 
    IT  bestb  13777  293 
    DE  bestb  55165  131090 
    DE  bestb  55165  293 
    DE  bestb  55165  293 
    DE  bestb  55165  293 
    DE  bestb  55165  293 
    CN  besto  24537  11450 
    GB  bidan  4584  58058 
    GB  bidan  4584  58058 
    IT  bimbu  4145  11700 
    GB  buy_d  97093  12576 
    GB  buy_d  97093  888 
    GB  buy_d  97093  888 
    GB  buy_d  97093  888 
    GB  buy_d  97093  159912 
    GB  buy_d  97093  888 
    GB  buy_d  97093  159912 
    GB  buy_d  97093  11700 
    GB  buy_d  97093  11700 
    GB  buy_d  97093  159912 
    GB  buy_d  97093  20710 
    GB  buy_d  97093  159912 
    GB  buy_d  97093  888 
    GB  buy_s  988538  11232 
    GB  buy_s  988538  1 
    GB  buy_s  988538  11700 
    GB  buy_s  988538  26395 

..現在我得到這個

code name  count  tcount map 
AD  Andorra   3  83141 andorra 
AU  Australia  14  83141 australia 
AT  Austria   345  83141 austria 
..... 
BE  Belgium   28  83141 belgium 
CN  China   1070 83141 china 
FR  France   4732 83141 france 
DE  Germany   33782 83141 germany 
HK  Hong Kong  364  83141 hongKong 
HU  Hungary   9  83141 hungary 
..... 
IN  India   10  83141 india 
IR  Iran   1  83141 iran 
IQ  Iraq   17  83141 iraq 
IE  Ireland   36  83141 ireland 
IL  Israel   16  83141 israel 
IT  Italy   5427 83141 italy 
JE  Jersey   25  83141 world 
.... 
GB  United Kingdom 35136 83141 unitedKingdom 

....

假設設置@Min到20我想得到這個:

code name   count tcount map 
AT  Austria   345  80945 austria 
BE  Belgium   28  80945 belgium 
CN  China   1070 80945 china 
FR  France   4732 80945 france 
DE  Germany   33782 80945 germany 
HK  Hong Kong  364  80945 hongKong 
IE  Ireland   36  80945 ireland 
IT  Italy   5427 80945 italy 
JE  Jersey   25  80945 world 
GB  United Kingdom 35136 80945 unitedKingdom 

其中,tcount是計數的總和

是否可以建議解決方法的路徑?

謝謝!

+1

您是否嘗試過'HAVING [統計]> @ Min'?不知道,但現在不能自己嘗試。 –

+0

是的,嘗試過,但(我想)因爲[count]是查詢內的計算字段不能用作參數 – Joe

+0

因爲'x.CountryId'出現在GROUP BY中,所以您不需要通過此進行分區。 HAVING與團隊的工作水平相同。在這種情況下,它將統計「CountryId,描述,地圖,用戶名」的唯一組合中的記錄數。 –

回答

1

你也許可以做到這樣簡單的東西..

SELECT c.countryid, 
     c.[description], 
     x.[count], 
     SUM([count]) OVER() [tcount], 
     COALESCE(c.Map,'world') [map] 
FROM global.dbo.countrydetails c 
     OUTER APPLY (
      SELECT COUNT(DISTINCT uc.username) [count] 
      FROM global.dbo.UserCategories uc 
      WHERE uc.countryid = c.countryid 
        AND TLCID LIKE @TLCID OR TLCID IN (@TLCID) 
        AND uc.Score BETWEEN @ScoreMin AND @ScoreMax 
     ) x 
WHERE x.[count] > @Min 

它會選擇單個用戶名計數,並將其應用到國家..那麼你可以總結的計數來獲得TCOUNT和過濾對個人計數

SQL Fiddle

+0

嗯..是的..看來,(再次!)外部應用是解決方案.. 將進行一些進一步的測試並讓你知道! – Joe

+0

'交叉應用'可能會給你更好的結果,因爲你正在過濾'Where'的結果,所以我會嘗試 – JamieD77

0

你似乎在這裏很親密。我認爲你讓它變得比需要的複雜。另外,子查詢中的where子句不完全正確。它可以簡化爲平等。

這應該是非常接近。

SELECT DISTINCT 
    x.CountryID [code], 
    c.Description [name], 
    COUNT(x.username) as [tcount], 
    COALESCE(c.Map,'world') [map] 
FROM 
(
    SELECT DISTINCT 
     CountryID, 
     username, 
     Score 
    FROM global.dbo.UserCategories 
    WHERE TLCID = @TLCID 
) x 
JOIN global.dbo.countrydetails c on x.CountryID=c.country 
AND x.Score BETWEEN @ScoreMin AND @ScoreMax 
GROUP BY x.CountryID, c.Description, c.Map 
HAVING COUNT(x.username) > @Min 
ORDER BY [name] ASC 

- 編輯 -

它是具有挑戰性弄清楚你想要什麼,因爲我們沒有桌子,沒有樣本數據,並沒有期望的輸出。總之,任何人都可以做的最好,它猜測你可能想要什麼。這是一篇很好的文章,它解釋了你應該在在線論壇上發佈t-sql幫助。 http://spaghettidba.com/2015/04/24/how-to-post-a-t-sql-question-on-a-public-forum/

這是另一種猜測,你可能想要什麼。我注意到你有明顯的分組。這是多餘的。

with CompiledValues as 
(
    SELECT x.CountryID as [code], 
     c.Description as [name], 
     COUNT(x.username) OVER(PARTITION BY x.countryID) as [count], 
     COUNT(x.username) OVER() as [tcount], 
     COALESCE(c.Map,'world') [map] 
    FROM 
    (
     SELECT DISTINCT 
      CountryID, 
      username 
     FROM global.dbo.UserCategories 
     WHERE TLCID = @TLCID 
    ) x 
    JOIN global.dbo.countrydetails c on x.CountryID = c.country 
     AND x.Score BETWEEN @ScoreMin AND @ScoreMax 
    GROUP BY x.CountryID 
     , c.Description 
     , c.Map 
) 

select * 
from CompiledValues 
where tcount > @Min 
ORDER BY [name] ASC 
+0

嗨肖恩,謝謝你的回答,是的,這解決了HAVING問題,但你刪除了[tcount]字段(你重命名[count]爲[tcount])。在[tcount]我有所有國家的用戶總數,我不能等待循環的結束來計算,因爲我需要事先知道,因爲它用於一些計算 – Joe

+0

是的,你是對的..但因爲數據是相當複雜的這一次我想避免,但一直沒有一個好主意..只是增加了一些 – Joe

0

似乎你想在選擇國家/用戶名時作出此決定。問題是如果用戶可以有> 1分,並且您想要這部分確定您的門檻計數。

-- Filtering by Count of CountryID, username, Score 
SELECT DISTINCT 
    x.CountryID [code], 
    c.Description [name], 
    COUNT(x.username) OVER(PARTITION BY x.countryID) [count], 
    COUNT(x.username) OVER() [tcount], 
    COALESCE(c.Map,'world') [map] 
FROM 
(
    SELECT COUNT(*), 
     CountryID, 
     username, 
     Score 
    FROM global.dbo.UserCategories 
    WHERE TLCID LIKE @TLCID OR TLCID IN (@TLCID) 
    GROUP BY CountryID, 
     username, 
     Score 
    HAVING COUNT(*) > [Your_Threshold_Number] 
) x 
JOIN global.dbo.countrydetails c on x.CountryID=c.country 
AND x.Score BETWEEN @ScoreMin AND @ScoreMax 
GROUP BY x.CountryID, c.Description, c.Map, x.username 
ORDER BY [name] ASC 

-- Filtering by Count of CountryID, username 
SELECT DISTINCT 
    x.CountryID [code], 
    c.Description [name], 
    COUNT(x.username) OVER(PARTITION BY x.countryID) [count], 
    COUNT(x.username) OVER() [tcount], 
    COALESCE(c.Map,'world') [map] 
FROM 
(
    SELECT COUNT(*), 
     CountryID, 
     username, 
     Score 
    FROM global.dbo.UserCategories AS g1 
    JOIN (SELECT COUNT(*) AS Cnt, 
     CountryID, 
     username 
    FROM global.dbo.UserCategories 
    GROUP BY CountryID, 
     username 
    HAVING COUNT(*) > [Your_Threshold_Number] 
    ) g2 ON g1.CountryID = g2.CountryID 
    WHERE TLCID LIKE @TLCID OR TLCID IN (@TLCID) 
    GROUP BY CountryID, 
     username, 
     Score 
) x 
JOIN global.dbo.countrydetails c on x.CountryID=c.country 
AND x.Score BETWEEN @ScoreMin AND @ScoreMax 
GROUP BY x.CountryID, c.Description, c.Map, x.username 
ORDER BY [name] ASC