Ich versuche Folgendes zu schreiben, um eine laufende Summe unterschiedlicher NumUsers zu erhalten:
NumUsers = COUNT(DISTINCT [UserAccountKey]) OVER (PARTITION BY [Mth])
Das Management Studio scheint darüber nicht allzu glücklich zu sein. Der Fehler verschwindet, wenn ich das DISTINCT
Schlüsselwort entferne , aber dann wird es nicht eindeutig gezählt.
DISTINCT
scheint innerhalb der Partitionsfunktionen nicht möglich zu sein. Wie finde ich die eindeutige Anzahl? Benutze ich eine traditionellere Methode wie eine korrelierte Unterabfrage?
Wenn Sie dies etwas OVER
genauer untersuchen, funktionieren diese Funktionen möglicherweise anders als Oracle, da sie nicht SQL-Server
zur Berechnung der laufenden Summen verwendet werden können.
Ich habe hier auf SQLfiddle ein Live-Beispiel hinzugefügt, in dem ich versuche, mithilfe einer Partitionsfunktion eine laufende Summe zu berechnen.
quelle
COUNT
mitORDER BY
stattPARTITION BY
schlecht definiert ist , im Jahr 2008. Ich bin überrascht , es ist so dass Sie es überhaupt haben. Gemäß der Dokumentation ist es Ihnen nicht gestattet,ORDER BY
eine Aggregatfunktion zu verwenden.Antworten:
Es gibt eine sehr einfache Lösung mit
dense_rank()
Auf diese Weise erhalten Sie genau das, wonach Sie gefragt haben: Die Anzahl der unterschiedlichen UserAccountKeys pro Monat.
quelle
dense_rank()
ist, dass NULL-Werte gezählt werden, währendCOUNT(field) OVER
dies nicht der Fall ist. Ich kann es aus diesem Grund nicht in meiner Lösung verwenden, aber ich denke immer noch, dass es ziemlich klug ist.NULL
Werte in der gebenUserAccountKey
kann, müssen Sie diesen Begriff hinzufügen :-MAX(CASE WHEN UserAccountKey IS NULL THEN 1 ELSE 0 END) OVER (PARTITION BY Mth)
. Die Idee stammt aus der Antwort von LarsRönnbäck unten. Im Wesentlichen , wennUserAccountKey
hatNULL
Werte, müssen Sie zusätzlich subtrahieren1
aus dem Ergebnis, daDENSE_RANK
zählt NULLs.dense_rank
Lösung, wenn die Fensterfunktion einen Rahmen hat. SQL Server erlaubt diedense_rank
Verwendung mit einem Fensterrahmen nicht: stackoverflow.com/questions/63527035/…Nekromantie:
Es ist relativ einfach, einen COUNT DISTINCT über PARTITION BY mit MAX über DENSE_RANK zu emulieren:
Hinweis:
Dies setzt voraus, dass die fraglichen Felder NICHT nullfähige Felder sind.
Wenn die Felder einen oder mehrere NULL-Einträge enthalten, müssen Sie 1 subtrahieren.
quelle
Ich denke, die einzige Möglichkeit, dies in SQL-Server 2008R2 zu tun, besteht darin, eine korrelierte Unterabfrage oder eine äußere Anwendung zu verwenden:
Dies kann in SQL-Server 2012 mit der von Ihnen vorgeschlagenen Syntax erfolgen:
Die Verwendung von
DISTINCT
ist jedoch immer noch nicht zulässig. Wenn also DISTINCT erforderlich ist und / oder wenn ein Upgrade nicht möglich ist,OUTER APPLY
ist dies meiner Meinung nach die beste Optionquelle
Ich verwende eine Lösung, die der von David oben ähnlich ist , aber mit einer zusätzlichen Wendung, wenn einige Zeilen von der Zählung ausgeschlossen werden sollen. Dies setzt voraus, dass [UserAccountKey] niemals null ist.
Eine SQL-Geige mit einem erweiterten Beispiel finden Sie hier.
quelle
[Include]
die Sie in Ihrer Antwort sprechen) mitdense_rank()
Arbeit zuUserAccountKey
erstellen, wenn dies möglich istNULL
. Fügen Sie diesen Begriff der Formel hinzu :-MAX(CASE WHEN UserAccountKey IS NULL THEN 1 ELSE 0 END) OVER (PARTITION BY Mth)
.