2016-04-15 12 views
0

Ich habe die folgende Abfrage:SQL Server HAVING COUNT OVER Ausgabe

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 

, die für jedes Land die Anzahl der Benutzer eine bestimmte Punktzahl und aktiv in bestimmten Kategorien mit Ich möchte aus den Listen Länder auszuschließen mit wenigen Nutzern und ich dachte, die HAVING-Klausel hinzufügen, aber sQL sagt mir

„Windowed Funktionen können nur in der SELECT oder ORDER BY Klauseln erscheinen.“

die wichtigste Tabelle ist CountryDetails die wie folgt aussieht:

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 

Ergebnis in Bezug auf .. jetzt bekomme ich diese

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 

....

unter der Annahme gesetzt @Min bis 20 Ich möchte Folgendes erhalten:

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 

wobei tcount die Summe der Anzahl ist

Kann Pls den Pfad für eine Problemumgehung vorschlagen?

Danke!

+1

Haben Sie versucht, erhalten 'MIT [count]> @ Min'? Nicht sicher, kann es jetzt nicht selbst ausprobieren. –

+0

ja, versucht, aber (ich nehme an) da [count] ist eine berechnete Felder innerhalb der Abfrage kann nicht als Parameter verwendet werden – Joe

+0

Da 'x.CountryId' in der GROUP BY angezeigt wird, müssen Sie nicht durch diese Partition. Das HAVING arbeitet auf der gleichen Ebene wie die Gruppe. In diesem Fall wird die Anzahl der Datensätze innerhalb der eindeutigen Kombinationen von "CountryId, Description, Map, Username" gezählt. –

Antwort

1

Sie könnten in der Lage sein, etwas so einfach, wie dies zu tun ..

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 

es werden die einzelnen Benutzernamen zählt auswählen und sie in den Ländern gelten ..dann können Sie die Zählungen Summe tcount und Filter auf die einzelnen zählt

SQL Fiddle

+0

hmmm .. ja .. es scheint, dass (wieder!) äußere Anwendung ist die Lösung .. wird einige weitere Tests machen und lassen Sie wissen! – Joe

+0

'Cross Apply' könnte Ihnen bessere Ergebnisse liefern, da Sie nach den Ergebnissen im' Where' filtern, also würde ich beides versuchen – JamieD77

0

Sie scheinen hier ziemlich nah zu sein. Ich denke, du hast es komplizierter gemacht, als es sein muss. Außerdem ist Ihre Where-Klausel im Subselect nicht ganz richtig. Es kann auf Gleiches vereinfacht werden.

Das sollte ziemlich nah sein.

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 

--EDIT--

Es ist eine Herausforderung, was Sie, weil wir keine Tabellen haben wollen, um herauszufinden, keine Probendaten und keine gewünschte Ausgabe. Kurz gesagt, das Beste, was irgendjemand gerade tun kann, rät, was Sie vielleicht wollen. Dies ist ein guter Artikel, der erklärt, was Sie für die t-sql-Hilfe in Online-Foren posten sollten. http://spaghettidba.com/2015/04/24/how-to-post-a-t-sql-question-on-a-public-forum/

Hier ist eine weitere Vermutung, was Sie wollen. Ich habe bemerkt, dass du klar und gruppiert bist. Dies ist redundant.

+0

Hallo Sean, danke für die Antwort, ja das löst das HAVING-Problem, aber du hast mir das Feld [tcount] entfernt (du hast [count] in [tcount] umbenannt). in [tcount] hatte ich die Gesamtzahl der Benutzer aller Länder, und ich kann nicht warten, bis das Ende der Schleife zu berechnen, da ich im Voraus wissen müssen, da es für einige Berechnungen verwendet wird – Joe

+0

ja, du hast Recht .. aber Da die Daten dieses Mal ziemlich komplex waren, dachte ich, sie zu vermeiden, aber war keine gute Idee .. nur hinzugefügt – Joe

0

Scheint so, als ob Sie diese Bestimmung treffen möchten, wenn Sie Land/Benutzername wählen. Die Frage ist, ob ein Benutzer> 1 Punkte haben kann und ob Sie diesen Teil zur Bestimmung Ihrer Schwellenzahl verwenden möchten.

-- 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