Dies ist in gewisser Weise eine Erweiterung von Lennarts Lösung , aber es ist so hässlich, dass ich es nicht wage, es als Bearbeitung vorzuschlagen. Ziel ist es, die Ergebnisse ohne abgeleitete Tabelle zu erhalten. Möglicherweise besteht dafür nie die Notwendigkeit, und in Verbindung mit der Hässlichkeit der Abfrage scheint das gesamte Unternehmen wie eine vergebliche Anstrengung zu sein. Ich wollte dies dennoch als Übung machen und möchte nun mein Ergebnis teilen:
SELECT
Col_A,
Col_B,
DistinctCount = DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B ASC )
+ DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B DESC)
- 1
- CASE COUNT(Col_B) OVER (PARTITION BY Col_A)
WHEN COUNT( * ) OVER (PARTITION BY Col_A)
THEN 0
ELSE 1
END
FROM
dbo.MyTable
;
Der Kern der Berechnung ist folgender (und ich möchte zunächst darauf hinweisen, dass die Idee nicht meine ist, ich habe an anderer Stelle von diesem Trick erfahren):
DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B ASC )
+ DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B DESC)
- 1
Dieser Ausdruck kann ohne Änderung verwendet werden, wenn Col_Bgarantiert ist, dass die Werte in niemals Nullen enthalten. Wenn die Spalte jedoch Nullen enthalten kann, müssen Sie dies berücksichtigen, und genau dafür ist der CASEAusdruck da. Es vergleicht die Anzahl der Zeilen pro Partition mit der Anzahl der Col_BWerte pro Partition. Wenn sich die Zahlen unterscheiden, bedeutet dies, dass einige Zeilen eine Null in haben Col_Bund daher die anfängliche Berechnung ( DENSE_RANK() ... + DENSE_RANK() - 1) um 1 reduziert werden muss.
Da das - 1Teil der Kernformel ist, habe ich es so belassen. Es kann jedoch tatsächlich in den CASEAusdruck aufgenommen werden, um die gesamte Lösung weniger hässlich erscheinen zu lassen:
SELECT
Col_A,
Col_B,
DistinctCount = DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B ASC )
+ DENSE_RANK() OVER (PARTITION BY Col_A ORDER BY Col_B DESC)
- CASE COUNT(Col_B) OVER (PARTITION BY Col_A)
WHEN COUNT( * ) OVER (PARTITION BY Col_A)
THEN 1
ELSE 2
END
FROM
dbo.MyTable
;
Diese Live-Demo auf
db <> fiddle.uk kann verwendet werden, um beide Variationen der Lösung zu testen.