计算不同的分区
Count distinct over partition by
我正在尝试对按角色划分的名称进行不同的计数。因此,在下面的示例中:我有一个 table,其中包含姓名和此人的角色。
我想要一个角色计数列,它给出了担任该角色的不同人员的总数。例如,角色经理出现了四次,但只有 3 个不同的人担任该角色 - Sam 在不同的日期再次出现。
如果我删除日期列,它可以正常使用:
select
a.date,
a.Name,
a.Role,
count(a.Role) over (partition by a.Role) as Role_Count
from table a
group by a.date, a.name, a.role
包括日期列然后使其计算角色总数而不是按不同的名称(我知道我没有在分区中标识)。给4个经理和3个分析师。
我该如何解决这个问题?
期望的输出:
Date
Name
Role
Role_Count
01/01
Sam
Manager
3
02/01
Sam
Manager
3
01/01
John
Manager
3
01/01
Dan
Manager
3
01/01
Bob
Analyst
2
02/01
Bob
Analyst
2
01/01
Mike
Analyst
2
当前输出:
Date
Name
Role
Role_Count
01/01
Sam
Manager
4
02/01
Sam
Manager
4
01/01
John
Manager
4
01/01
Dan
Manager
4
01/01
Bob
Analyst
3
02/01
Bob
Analyst
3
01/01
Mike
Analyst
3
遗憾的是,COUNT(DISTINCT
不可用作 window 聚合。但是我们可以用DENSE_RANK
和MAX
的组合来模拟一下:
select
a.Name,
a.Role,
MAX(rnk) OVER (PARTITION BY date, Role) as Role_Count
from (
SELECT *,
DENSE_RANK() OVER (PARTITION BY date, Role ORDER BY Name) AS rnk
FROM table
) a
如果 Name
可能有空值,那么我们需要考虑到这一点:
select
a.Name,
a.Role,
MAX(CASE WHEN Name IS NOT NULL THEN rnk END) OVER (PARTITION BY date, Role) as Role_Count
from (
SELECT *,
DENSE_RANK() OVER (PARTITION BY date, Role, CASE WHEN Name IS NULL THEN 0 ELSE 1 END ORDER BY Name) AS rnk
FROM table
) a
不幸的是,SQL 服务器(以及其他数据库)不支持 COUNT(DISTINCT)
作为 window 函数。幸运的是,有一个简单的技巧可以解决这个问题——DENSE_RANK()
s 的总和减一:
select a.Name, a.Role,
(dense_rank() over (partition by a.Role order by a.Name asc) +
dense_rank() over (partition by a.Role order by a.Name desc) -
1
) as distinct_names_in_role
from table a
group by a.name, a.role
我正在尝试对按角色划分的名称进行不同的计数。因此,在下面的示例中:我有一个 table,其中包含姓名和此人的角色。
我想要一个角色计数列,它给出了担任该角色的不同人员的总数。例如,角色经理出现了四次,但只有 3 个不同的人担任该角色 - Sam 在不同的日期再次出现。
如果我删除日期列,它可以正常使用:
select
a.date,
a.Name,
a.Role,
count(a.Role) over (partition by a.Role) as Role_Count
from table a
group by a.date, a.name, a.role
包括日期列然后使其计算角色总数而不是按不同的名称(我知道我没有在分区中标识)。给4个经理和3个分析师。
我该如何解决这个问题?
期望的输出:
Date | Name | Role | Role_Count |
---|---|---|---|
01/01 | Sam | Manager | 3 |
02/01 | Sam | Manager | 3 |
01/01 | John | Manager | 3 |
01/01 | Dan | Manager | 3 |
01/01 | Bob | Analyst | 2 |
02/01 | Bob | Analyst | 2 |
01/01 | Mike | Analyst | 2 |
当前输出:
Date | Name | Role | Role_Count |
---|---|---|---|
01/01 | Sam | Manager | 4 |
02/01 | Sam | Manager | 4 |
01/01 | John | Manager | 4 |
01/01 | Dan | Manager | 4 |
01/01 | Bob | Analyst | 3 |
02/01 | Bob | Analyst | 3 |
01/01 | Mike | Analyst | 3 |
遗憾的是,COUNT(DISTINCT
不可用作 window 聚合。但是我们可以用DENSE_RANK
和MAX
的组合来模拟一下:
select
a.Name,
a.Role,
MAX(rnk) OVER (PARTITION BY date, Role) as Role_Count
from (
SELECT *,
DENSE_RANK() OVER (PARTITION BY date, Role ORDER BY Name) AS rnk
FROM table
) a
如果 Name
可能有空值,那么我们需要考虑到这一点:
select
a.Name,
a.Role,
MAX(CASE WHEN Name IS NOT NULL THEN rnk END) OVER (PARTITION BY date, Role) as Role_Count
from (
SELECT *,
DENSE_RANK() OVER (PARTITION BY date, Role, CASE WHEN Name IS NULL THEN 0 ELSE 1 END ORDER BY Name) AS rnk
FROM table
) a
不幸的是,SQL 服务器(以及其他数据库)不支持 COUNT(DISTINCT)
作为 window 函数。幸运的是,有一个简单的技巧可以解决这个问题——DENSE_RANK()
s 的总和减一:
select a.Name, a.Role,
(dense_rank() over (partition by a.Role order by a.Name asc) +
dense_rank() over (partition by a.Role order by a.Name desc) -
1
) as distinct_names_in_role
from table a
group by a.name, a.role