Ini, dengan cara tertentu, merupakan perluasan dari solusi Lennart , tetapi sangat jelek sehingga saya tidak berani menyarankannya sebagai hasil edit. Tujuannya di sini adalah untuk mendapatkan hasil tanpa tabel turunan. Mungkin tidak pernah ada kebutuhan untuk itu, dan dikombinasikan dengan keburukan dari permintaan, seluruh upaya itu mungkin tampak seperti usaha yang sia-sia. Saya masih ingin melakukan ini sebagai latihan, dan sekarang ingin membagikan hasil saya:
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
;
Bagian inti dari perhitungan adalah ini (dan pertama-tama saya ingin mencatat bahwa idenya bukan milik saya, saya belajar tentang trik ini di tempat lain):
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
Ekspresi ini dapat digunakan tanpa perubahan apa pun jika nilai dalam Col_Bdijamin tidak pernah memiliki null. Namun, jika kolom memiliki nol, Anda harus memperhitungkannya, dan itulah tepatnya yang dimaksud dengan CASEekspresi itu. Ini membandingkan jumlah baris per partisi dengan jumlah Col_Bnilai per partisi. Jika angkanya berbeda, itu berarti bahwa beberapa baris memiliki nol Col_Bdan, oleh karena itu, perhitungan awal ( DENSE_RANK() ... + DENSE_RANK() - 1) perlu dikurangi dengan 1.
Perhatikan bahwa karena - 1ini adalah bagian dari formula inti, saya memilih untuk membiarkannya seperti itu. Namun, itu sebenarnya dapat dimasukkan ke dalam CASEekspresi, dalam upaya yang sia-sia untuk membuat seluruh solusi terlihat kurang jelek:
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
;
Demo langsung ini di
db <> fiddle.uk dapat digunakan untuk menguji kedua variasi solusi.