当前位置: 首页 > 面试题库 >

redshift:通过窗口分区计算不重复的客户

纪翰
2023-03-14
问题内容

RedshiftDISTINCT在其窗口函数中不支持聚合。
AWS文档的COUNT状态为this
distinct任何窗口功能均不支持。

我的用例:在不同的时间间隔和流量渠道上统计客户

我希望获得当年的月度和年初至今 唯一
客户数,并希望按流量渠道以及所有渠道的总数进行划分。由于一个客户可以拜访不止一次,因此我只需要计算不同的客户,因此Redshift窗口汇总将无济于事。

  • 我可以使用来计算不同的客户count(distinct customer_id)...group by,但这只会给我四个所需结果的一个。
  • 并不 想进入运行了一堆之间堆积每个需要计数一个完整的查询习惯union all。我希望这不是唯一的解决方案。

这就是我在postgres(或Oracle)中写的内容:

select order_month
       , traffic_channel
       , count(distinct customer_id) over(partition by order_month, traffic_channel) as customers_by_channel_and_month
       , count(distinct customer_id) over(partition by traffic_channel) as ytd_customers_by_channel
       , count(distinct customer_id) over(partition by order_month) as monthly_customers_all_channels
       , count(distinct customer_id) over() as ytd_total_customers

from orders_traffic_channels
/* otc is a table of dated transactions of customers, channels, and month of order */

where to_char(order_month, 'YYYY') = '2017'

如何在Redshift中解决此问题?

结果需要在redshift集群上工作,此外,这是一个简化的问题,实际的期望结果具有产品类别和客户类型,这乘以所需分区的数量。因此,堆栈union all汇总不是一个很好的解决方案。


问题答案:

2016年的博客文章指出了这个问题,并提供了一个基本的解决方法,因此谢谢Mark D.
Adams。奇怪的是,我在所有的网络上都找不到,因此我正在共享我的(经过测试的)解决方案。

关键的见解是dense_rank(),按相关商品排序,可以为相同商品提供相同的排名,因此,最高排名也是唯一商品的计数。如果您尝试为我想要的每个分区交换以下内容,那就太糟了:

dense_rank() over(partition by order_month, traffic_channel order by customer_id)

由于您需要最高的排名,因此您必须对所有内容进行子查询,然后从每个获得的排名中选择最大值。 重要的是将外部查询中的分区与子查询中的相应分区进行匹配。

/* multigrain windowed distinct count, additional grains are one dense_rank and one max over() */
select distinct
       order_month
       , traffic_channel
       , max(tc_mth_rnk) over(partition by order_month, traffic_channel) customers_by_channel_and_month
       , max(tc_rnk) over(partition by traffic_channel)  ytd_customers_by_channel
       , max(mth_rnk) over(partition by order_month)  monthly_customers_all_channels
       , max(cust_rnk) over()  ytd_total_customers

from (
       select order_month
              , traffic_channel
              , dense_rank() over(partition by order_month, traffic_channel order by customer_id)  tc_mth_rnk
              , dense_rank() over(partition by traffic_channel order by customer_id)  tc_rnk
              , dense_rank() over(partition by order_month order by customer_id)  mth_rnk
              , dense_rank() over(order by customer_id)  cust_rnk

       from orders_traffic_channels

       where to_char(order_month, 'YYYY') = '2017'
     )

order by order_month, traffic_channel
;

笔记

  • max()dense_rank()必须匹配的分区
  • dense_rank()将对null值进行排名(所有排名都在同一排名,即最大值)。如果您不希望对null值进行计数,则需要一个case when customer_id is not null then dense_rank() ...etc...,或者,max()如果您知道存在空值,则可以从中减去一个。


 类似资料:
  • 我正在构建一个执行大量客户端数据下载和处理的应用程序。数据处理通过在驻留在子域上的iframe中处理而与主应用程序隔离。下载数据的正是这个iframe。通讯是通过邮件传递的。 一切都很好,除了可能更好。 如果用户打开额外的选项卡/窗口,应用程序当前会重新加载所有数据,甚至可能进行重复的处理工作,这并不是什么问题,只是会减慢所有内容的速度,加载页面需要更长的时间。 我想做的是让每个顶级选项卡/窗口只

  • 问题内容: 我需要从表中删除重复项: 该列是主键。 我想知道如何在有多次出现的情况下仅保留最大的 问题答案: 将订单更改为。

  • 问题内容: 考虑一下您有一些不均匀的时间序列数据: 假设我想在1ms的时间内进行滚动求和: 目前,我将所有内容都放回多头,并在cython中进行,但是在纯熊猫中有可能吗?我知道您可以执行.asfreq(’U’)之类的操作,然后填充并使用传统函数,但是一旦行数超过玩具数量,就无法缩放。 作为参考,这是一个骇人的,不是快速的Cython版本: 在更大的系列上对此进行演示: 问题答案: 您可以使用求和和

  • 在Apache Flink中使用滑动时间窗口时,当窗口滑动时会重新计算窗口中的许多元组/元素。例如,假设一个窗口大小为5秒,滑动时间为1秒,则窗口内容的80%与上一个窗口的内容相同。 考虑一个数据流S,其元组由时间戳和整数值组成: , , , , , , ,... 假设t1、t2、t3、...表示连续时间戳,其中t2-t1=1秒。给定S,窗口大小为5秒、滑动1秒的Flink窗口化ProcessWi

  • 实现滑动窗口我写了这样的: 执行此代码将打印: 我正在尝试修改,以便每个窗口之间没有重叠,这样大小为3的滑动窗口将返回: 我想我需要修改<code>start</code>,使其指向下一个窗口,但我不确定如何使用流来实现这一点。

  • 问题内容: 样本数据可能会有助于解释我想做的事情,而不是解释它,因此,我将从此开始。 这是我目前正在使用的数据: 我正在尝试在15分钟的时间内滚动显示此数据中的出现次数。该数据的预期结果如下: 样本数据: 我可以通过以下方式 使它 起作用: 但是,我想避免使用子查询,而建议使用(或其他任何可能的解决方案)解决方案。 这可能吗?还是子查询是正确的解决方案? 问题答案: 一种方法-如果表很大,可能比嵌