PARTITION BY 只考虑两个特定的列进行聚合?

PARTITION BY to consider only two specific columns for aggregation?

我的 table 有以下数据:

REF_NO PRD_GRP ACC_NO
ABC 12 1234
ABC 9C 1234
防御 AB 7890
防御 TY 9891

我正在尝试构建一个查询来汇总每个客户的帐户数量 - 产品组与此目的无关,因此我的预期结果是:

REF_NO PRD_GRP ACC_NO NO_OF_ACC
ABC 12 1234 1
ABC 9C 1234 1
防御 AB 7890 2
防御 TY 9891 2

我尝试使用 window 函数执行此操作:

SELECT
    T.REF_NO,
    T.PRD_GRP,
    T.ACC_NO,
    COUNT(T.ACC_NO) OVER (PARTITION BY T.REF_NO) AS NUM_OF_ACC

FROM TABLE T

但是,在第一个客户 (ABC) 的上述示例中,返回的 NUM_OF_ACC 值是 2 而不是 1。查询似乎只是在计算每个客户的唯一行数,而不是根据需要确定帐户数。

我该如何解决这个错误?

Link 到 Fiddle - https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=83344cbe95fb46d4a1640caf0bb6d0b2

您需要的是 COUNT(DISTINCT T.ACC_NO),不幸的是 window 函数不支持它。因此,您必须编写一个子查询以允许您在没有 window 函数的情况下使用 COUNT(DISTINCT T.ACC_NO)

SELECT
    T.REF_NO,
    T.PRD_GRP,
    T.ACC_NO,
    -- Use of DISTINCT is not allowed with the OVER clause.
    -- COUNT(DISTINCT T.ACC_NO) OVER (PARTITION BY T.REF_NO) AS NUM_OF_ACC,
    (
        SELECT COUNT(DISTINCT T1.ACC_NO)
        FROM TEST_DATA T1
        WHERE T1.REF_NO = T.REF_NO
    ) AS NUM_OF_ACC
FROM TEST_DATA T

您需要 COUNT(DISTINCT,不幸的是 SQL 服务器不支持 window 功能。

但是你可以用DENSE_RANKMAX

来模拟
SELECT
    T.REF_NO,
    T.PRD_GRP,
    T.ACC_NO,
    MAX(T.rn) OVER (PARTITION BY T.REF_NO) AS NUM_OF_ACC
FROM (
    SELECT *,
        DENSE_RANK() OVER (PARTITION BY T.REF_NO ORDER BY T.ACC_NO) AS rn
    FROM [TABLE] T
) T;

DENSE_RANK 将计算按 ACC_NO 排序的行,但忽略关系,因此 MAX 将是不同值的数量。

db<>fiddle.uk

count(distinct) 作为 window 函数实现的最简单方法是将两个 dense_ranks():

相加
SELECT T.REF_NO, T.PRD_GRP, T.ACC_NO,
       (-1 +
         DENSE_RANK() OVER (PARTITION BY t.REF_NO ORDER BY T.ACC_NO ASC) +
         DENSE_RANK() OVER (PARTITION BY t.REF_NO ORDER BY T.ACC_NO DESC)
        ) as cnt_distinct
FROM TABLE T