Theo một cách nào đó, đây là một phần mở rộng cho giải pháp của Lennart , nhưng nó xấu đến mức tôi không dám đề xuất nó như là một chỉnh sửa. Mục tiêu ở đây là để có được kết quả mà không cần bảng dẫn xuất. Có thể không bao giờ cần điều đó, và kết hợp với sự xấu xí của truy vấn, toàn bộ nỗ lực có vẻ như là một nỗ lực lãng phí. Tôi vẫn muốn làm điều này như một bài tập, mặc dù, và bây giờ muốn chia sẻ kết quả của tôi:
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
;
Phần cốt lõi của phép tính là điều này (và trước hết tôi muốn lưu ý rằng ý tưởng không phải là của tôi, tôi đã tìm hiểu về thủ thuật này ở nơi khác):
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
Biểu thức này có thể được sử dụng mà không có bất kỳ thay đổi nào nếu các giá trị trong Col_B
được đảm bảo không bao giờ có giá trị null. Tuy nhiên, nếu cột có thể có giá trị null, bạn cần tính đến điều đó và đó chính xác là CASE
biểu thức có ở đó. Nó so sánh số lượng hàng trên mỗi phân vùng với số lượng Col_B
giá trị trên mỗi phân vùng. Nếu các số khác nhau, điều đó có nghĩa là một số hàng có giá trị null Col_B
và do đó, phép tính ban đầu ( DENSE_RANK() ... + DENSE_RANK() - 1
) cần phải giảm đi 1.
Lưu ý rằng vì - 1
là một phần của công thức cốt lõi, tôi đã chọn để nó như thế. Tuy nhiên, nó thực sự có thể được tích hợp vào CASE
biểu thức, trong nỗ lực vô ích để làm cho toàn bộ giải pháp trông bớt xấu xí:
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
;
Bản demo trực tiếp này tại db <> fiddle.uk có thể được sử dụng để kiểm tra cả hai biến thể của giải pháp.