ProgramingTip

DISTINCT를 사용하여 파티션 함수 COUNT () OVER 가능

bestdevel 2020. 11. 7. 10:21
반응형

DISTINCT를 사용하여 파티션 함수 COUNT () OVER 가능


다음과 같이 고유 한 Num Users가 많은 사람들을 위해 다음을 작성합니다.

NumUsers = COUNT(DISTINCT [UserAccountKey]) OVER (PARTITION BY [Mth])

관리 스튜디오는 이것에 대해 너무 행복해 이야기합니다. DISTINCT키워드를 제거하면 오류가 사라지 지만 고유 한 것은 아닙니다.

DISTINCT파티션 기능 내에서 가능하지 않을 것입니다. 고유 개수를 찾는 방법은 무엇입니까? 하위 쿼리와 상관 같은 보다 전통적인 방법을 사용 합니까?

더 자세히 살펴보면 좀 이러한 OVER함수는 SQL-Server누계 계산에 사용할 수없는 방식으로 오라클과 다르게 작동 할 수 있습니다 .

여기 SQLfiddle 에 실제 예제를 추가했습니다. 여기서 분할 함수를 사용하여 누계를 계산합니다.


사용하는 매우 간단한 솔루션이 있습니다. dense_rank()

dense_rank() over (partition by [Mth] order by [UserAccountKey]) 
+ dense_rank() over (partition by [Mth] order by [UserAccountKey] desc) 
- 1

이것은 당신이 요구했던 것을 정확하게 제공 할 것입니다 : 매월 고유 한 UserAccountKey의 수입니다.


SQL-Server 2008R2 에서이 작업을 수행하는 유일한 방법은 상관 하위 쿼리 또는 외부 적용을 사용하는 것입니다.

SELECT  datekey,
        COALESCE(RunningTotal, 0) AS RunningTotal,
        COALESCE(RunningCount, 0) AS RunningCount,
        COALESCE(RunningDistinctCount, 0) AS RunningDistinctCount
FROM    document
        OUTER APPLY
        (   SELECT  SUM(Amount) AS RunningTotal,
                    COUNT(1) AS RunningCount,
                    COUNT(DISTINCT d2.dateKey) AS RunningDistinctCount
            FROM    Document d2
            WHERE   d2.DateKey <= document.DateKey
        ) rt;

제안한 구문을 사용하여 SQL-Server 2012 에서이 작업을 수행 할 수 있습니다 .

SELECT  datekey,
        SUM(Amount) OVER(ORDER BY DateKey) AS RunningTotal
FROM    document

그러나 사용 DISTINCT은 여전히 ​​허용되지 않습니다. DISTINCT가 필요하거나 업그레이드가 옵션이 OUTER APPLY아닌 경우 최선의 선택 이라고 생각 합니다.


David 와 포함 솔루션을 사용 하지만 일부 행을 개수에서 제외해야하는 경우 추가 비틀기가 있습니다. 이것은 [UserAccountKey]가 null이 아니라 가정합니다.

-- subtract an extra 1 if null was ranked within the partition,
-- which only happens if there were rows where [Include] <> 'Y'
dense_rank() over (
  partition by [Mth] 
  order by case when [Include] = 'Y' then [UserAccountKey] else null end asc
) 
+ dense_rank() over (
  partition by [Mth] 
  order by case when [Include] = 'Y' then [UserAccountKey] else null end desc
)
- max(case when [Include] = 'Y' then 0 else 1 end) over (partition by [Mth])
- 1

확장 된 예제가있는 SQL Fiddle은 여기에서 사용할 수 있습니다.


네크 로맨싱 :

DENSE_RANK를 통해 MAX로 PARTITION BY COUNT DISTINCT를 에뮬레이션하는 것은 간단합니다.

;WITH baseTable AS
(
    SELECT 'RM1' AS RM, 'ADR1' AS ADR
    UNION ALL SELECT 'RM1' AS RM, 'ADR1' AS ADR
    UNION ALL SELECT 'RM2' AS RM, 'ADR1' AS ADR
    UNION ALL SELECT 'RM2' AS RM, 'ADR2' AS ADR
    UNION ALL SELECT 'RM2' AS RM, 'ADR2' AS ADR
    UNION ALL SELECT 'RM2' AS RM, 'ADR3' AS ADR
    UNION ALL SELECT 'RM3' AS RM, 'ADR1' AS ADR
    UNION ALL SELECT 'RM2' AS RM, 'ADR1' AS ADR
    UNION ALL SELECT 'RM3' AS RM, 'ADR1' AS ADR
    UNION ALL SELECT 'RM3' AS RM, 'ADR2' AS ADR
)
,CTE AS
(
    SELECT RM, ADR, DENSE_RANK() OVER(PARTITION BY RM ORDER BY ADR) AS dr 
    FROM baseTable
)
SELECT
     RM
    ,ADR

    ,COUNT(CTE.ADR) OVER (PARTITION BY CTE.RM ORDER BY ADR) AS cnt1 
    ,COUNT(CTE.ADR) OVER (PARTITION BY CTE.RM) AS cnt2 
    -- Not supported
    --,COUNT(DISTINCT CTE.ADR) OVER (PARTITION BY CTE.RM ORDER BY CTE.ADR) AS cntDist
    ,MAX(CTE.dr) OVER (PARTITION BY CTE.RM ORDER BY CTE.RM) AS cntDistEmu 
FROM CTE

참고 URL : https://stackoverflow.com/questions/11202878/partition-function-count-over-possible-using-distinct

반응형