De certa forma, isso é uma extensão da solução de Lennart , mas é tão feio que não ouso sugerir isso como uma edição. O objetivo aqui é obter os resultados sem uma tabela derivada. Pode nunca haver necessidade disso, e combinado com a feiúra da consulta, todo o esforço pode parecer um esforço desperdiçado. Eu ainda queria fazer isso como um exercício, e agora gostaria de compartilhar meu resultado:
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
;
A parte principal do cálculo é esta (e antes de mais nada, gostaria de observar que a ideia não é minha, aprendi sobre esse truque em outro lugar):
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
Essa expressão pode ser usada sem nenhuma alteração se Col_B
for garantido que os valores em nunca tenham nulos. Se a coluna pode ter nulos, no entanto, você precisa levar isso em conta, e é exatamente para isso que a CASE
expressão existe. Ele compara o número de linhas por partição com o número de Col_B
valores por partição. Se os números diferirem, isso significa que algumas linhas têm nulo Col_B
e, portanto, o cálculo inicial ( DENSE_RANK() ... + DENSE_RANK() - 1
) precisa ser reduzido em 1.
Observe que, como - 1
faz parte da fórmula principal, optei por deixá-la assim. No entanto, ele pode realmente ser incorporado à CASE
expressão, na tentativa fútil de fazer com que toda a solução pareça menos feia:
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
;
Esta demonstração ao vivo no db <> fiddle.uk pode ser usada para testar as duas variações da solução.