SQL 累计非重复计数
SQL a cumulative distinct count
我有一个 SQL table 列出了各个事件,我正在尝试聚合以获得一组事件,如下所示。
id |Name | Date|
0 |A |2018-05-08
1 |A |2018-05-09
2 |B |2018-05-11
3 |B |2018-05-12
4 |A |2018-05-17
5 |A |2018-05-17
6 |A |2018-05-18
7 |C |2018-05-25
8 |C |2018-05-26
9 |B |2018-05-27
变为:
Name|Group
|A |1
|B |2
|A |3
|C |4
|B |5
我认为这是某种形式的 Count(),然后是 OVER BY,这总是让我感到困惑。我什至不知道我会计算什么,因为几乎没有将这些名字组合在一起。到目前为止,我有以下内容:
select
Name
,Count(Name)
from table
Group BY
Name
这是一个间隙和孤岛问题,您希望将 "adjacent" 行组合在一起。
一种方法依靠行号之间的差异来识别组。如果 id
持续增加 1
,请考虑:
select
name,
row_number() over(partition by name, id - rn order by min(date)) grp
from (
select
t.*,
row_number() over(partition by name order by date) rn
from mytable t
) t
group by name, id - rn
order by grp
否则,我们可以用row_number()
生成id
:
select
name,
row_number() over(partition by name, rn1 - rn2 order by min(date)) grp
from (
select
t.*,
row_number() over(order by date) rn1,
row_number() over(partition by name order by date) rn2
from mytable t
) t
group by name, rn1 - rn2
order by grp
没有理由将此视为间隙和孤岛问题。我的意思是,它是,但有一个更简单的解决方案。
在这种情况下,使用 lag()
和 row_number()
:
select name, row_number() over (order by date, id) as grp
from (select t.*,
lag(name) over (order by date, id) as prev_name
from t
) t
where prev_name is null or prev_name <> name;
我有一个 SQL table 列出了各个事件,我正在尝试聚合以获得一组事件,如下所示。
id |Name | Date|
0 |A |2018-05-08
1 |A |2018-05-09
2 |B |2018-05-11
3 |B |2018-05-12
4 |A |2018-05-17
5 |A |2018-05-17
6 |A |2018-05-18
7 |C |2018-05-25
8 |C |2018-05-26
9 |B |2018-05-27
变为:
Name|Group
|A |1
|B |2
|A |3
|C |4
|B |5
我认为这是某种形式的 Count(),然后是 OVER BY,这总是让我感到困惑。我什至不知道我会计算什么,因为几乎没有将这些名字组合在一起。到目前为止,我有以下内容:
select
Name
,Count(Name)
from table
Group BY
Name
这是一个间隙和孤岛问题,您希望将 "adjacent" 行组合在一起。
一种方法依靠行号之间的差异来识别组。如果 id
持续增加 1
,请考虑:
select
name,
row_number() over(partition by name, id - rn order by min(date)) grp
from (
select
t.*,
row_number() over(partition by name order by date) rn
from mytable t
) t
group by name, id - rn
order by grp
否则,我们可以用row_number()
生成id
:
select
name,
row_number() over(partition by name, rn1 - rn2 order by min(date)) grp
from (
select
t.*,
row_number() over(order by date) rn1,
row_number() over(partition by name order by date) rn2
from mytable t
) t
group by name, rn1 - rn2
order by grp
没有理由将此视为间隙和孤岛问题。我的意思是,它是,但有一个更简单的解决方案。
在这种情况下,使用 lag()
和 row_number()
:
select name, row_number() over (order by date, id) as grp
from (select t.*,
lag(name) over (order by date, id) as prev_name
from t
) t
where prev_name is null or prev_name <> name;