Это, в некотором смысле, расширение решения Леннарта , но это настолько уродливо, что я не смею предлагать его в качестве редактирования. Цель здесь - получить результаты без производной таблицы. Возможно, в этом никогда не будет необходимости, и в сочетании с уродливостью запроса все усилия могут показаться бесполезными. Я все еще хотел сделать это как упражнение, и теперь хотел бы поделиться своим результатом:
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
;
Основная часть расчета заключается в следующем (и я хотел бы прежде всего отметить, что идея не моя, я узнал об этой уловке в другом месте):
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
Это выражение может использоваться без каких-либо изменений, если значения в Col_B
гарантированно никогда не будут иметь нулевые значения. Однако, если столбец может иметь значения NULL, вам необходимо учесть это, и именно для этого и существует CASE
выражение. Он сравнивает количество строк на раздел с количеством Col_B
значений на раздел. Если числа различаются, это означает, что некоторые строки имеют нулевое значение вCol_B
и поэтому первоначальный расчет ( DENSE_RANK() ... + DENSE_RANK() - 1
) необходимо уменьшить на 1.
Обратите внимание, что поскольку это - 1
является частью основной формулы, я решил оставить это так. Тем не менее, он может быть включен в CASE
выражение в тщетной попытке сделать все решение менее уродливым:
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
;
Это живое демо на db <> fiddle.uk можно использовать для тестирования обоих вариантов решения.