Esto es, en cierto modo, una extensión de la solución de Lennart , pero es tan feo que no me atrevo a sugerirlo como una edición. El objetivo aquí es obtener los resultados sin una tabla derivada. Puede que nunca sea necesario, y combinado con la fealdad de la consulta, todo el esfuerzo puede parecer un esfuerzo perdido. Sin embargo, todavía quería hacer esto como ejercicio, y ahora me gustaría compartir mi 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
;
La parte central del cálculo es esta (y en primer lugar me gustaría señalar que la idea no es mía, aprendí sobre este truco en otro 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
Esta expresión se puede usar sin ningún cambio si Col_B
se garantiza que los valores nunca tendrán valores nulos. Sin embargo, si la columna puede tener valores nulos, debe tener en cuenta eso, y para eso está exactamente la CASE
expresión. Compara el número de filas por partición con el número de Col_B
valores por partición. Si los números difieren, significa que algunas filas tienen un valor nulo Col_B
y, por lo tanto, el cálculo inicial ( DENSE_RANK() ... + DENSE_RANK() - 1
) debe reducirse en 1.
Tenga en cuenta que debido a que - 1
es parte de la fórmula central, elegí dejarlo así. Sin embargo, en realidad puede incorporarse a la CASE
expresión, en el intento inútil de hacer que la solución completa se vea menos fea:
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 demostración en vivo en db <> fiddle.uk se puede usar para probar ambas variaciones de la solución.