Spark SQL 的累积非重复计数

Posted

技术标签:

【中文标题】Spark SQL 的累积非重复计数【英文标题】:Cumulative distinct count with Spark SQL 【发布时间】:2017-06-27 13:01:04 【问题描述】:

使用 Spark 1.6.2。

这里是数据:

day | visitorID
-------------
1   | A
1   | B
2   | A
2   | C
3   | A
4   | A

我想计算每天有多少不同的访问者+前一天的累积(我不知道确切的术语,抱歉)。

这应该给出:

day | visitors
--------------
 1  | 2 (A+B)
 2  | 3 (A+B+C)
 3  | 3 
 4  | 3
尝试了自加入,但速度太慢了 我确定窗口函数是我正在寻找的,但没能找到它:/

【问题讨论】:

SQL Server 不是 Spark SQL。 您在寻找 spark 或 sql-server 的解决方案吗? 你是对的,只有Spark SQL,没有注意自动完成对不起。 【参考方案1】:

你应该可以做到:

select day, max(visitors) as visitors
from (select day,
             count(distinct visitorId) over (order by day) as visitors
      from t
     ) d
group by day;

实际上,我认为更好的方法是仅在访客出现的第一天记录访客:

select startday, sum(count(*)) over (order by startday) as visitors
from (select visitorId, min(day) as startday
      from t
      group by visitorId
     ) t
group by startday
order by startday;

【讨论】:

运行第一个查询给出错误:expression 'day' is neither present in the group by, nor is it an aggregate function.(在 spark 1.6.2 下) 第一个代码对我也不起作用,但第二个代码运行良好。【参考方案2】:

在 SQL 中,您可以这样做。

select t1.day,sum(max(t.cnt)) over(order by t1.day) as visitors
from tbl t1
left join (select minday,count(*) as cnt 
           from (select visitorID,min(day) as minday 
                 from tbl 
                 group by visitorID
                ) t 
           group by minday
          ) t 
on t1.day=t.minday
group by t1.day
使用min 获取visitorID 出现的第一天。 按上面找到的此类 minday 计算行数。 将此加入到您的原始表中并获得累积总和。

另一种方法是

select t1.day,sum(count(t.visitorid)) over(order by t1.day) as cnt 
from tbl t1
left join (select visitorID,min(day) as minday 
           from tbl 
           group by visitorID
          ) t 
on t1.day=t.minday and t.visitorid=t1.visitorid
group by t1.day

【讨论】:

【参考方案3】:

试试看

select
    day,
    count(*),
    (
    select count(*) from your_table b
    where a.day >= b.day
    ) cumulative
from your_table as a
group by a.day
order by 1 

【讨论】:

Spark 1.6.2 不允许这样的子查询:/

以上是关于Spark SQL 的累积非重复计数的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spark Scala 中的 Schema RDD [从案例类中创建] 中查找重复项以及相应的重复计数?

Spark Structured Streaming - 如何按最新和聚合计数进行重复数据删除

SQL查找不同值计数,2次重复值计数,3次重复值计数等

SQL 累积不重复计数

为啥我的“org.apache.spark.sql”下面没有“SparkSession”[重复]

SQL:如何获取计数值的 sum() [重复]