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_RANK
和MAX
来模拟
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
将是不同值的数量。
将 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
我的 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_RANK
和MAX
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
将是不同值的数量。
将 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