이것은 어떤 방식으로 Lennart의 솔루션에 대한 확장 이지만, 편집으로 제안하지 않는 것이 너무 추합니다. 여기서 목표는 파생 테이블없이 결과를 얻는 것입니다. 그럴 필요가 없을 수도 있고, 질의의 추악함과 결합하여 모든 노력이 낭비되는 것처럼 보일 수 있습니다. 그래도 나는 이것을 운동으로하고 싶었고 이제 결과를 공유하고 싶습니다.
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.