回答

收藏

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

技术问答 技术问答 316 人阅读 | 0 人回复 | 2023-09-14

RedshiftDISTINCT不支持其窗口函数中的聚合。
3 _( ~8 K+ Z4 {9 o- q! sAWS文档的COUNT状态为this,distinct不支持任何窗口功能。
4 I1 a9 M1 h; m; }我的用例:统计不同时间间隔和流量渠道的客户我希望得到当年的月度和年初到现在 唯一: ]. c+ i  E9 q9 b) M! F* p3 G
客户数量,希望根据流量渠道和所有渠道的总数进行划分。因为一个客户可以访问不止一次,我只需要计算不同的客户,所以Redshift窗口汇总将无济于事。
0 f' L- S# Z5 T我可以用它来计算不同的客户count(distinct customer_id)...group by,但这只会给我四个所需的结果。/ |0 L% x/ M# Y% ?9 s
并不    如果你想进入一堆,你需要计数一个完整的查询习惯union all。我希望这不是唯一的解决方案。
这就是我在postgres(或Oracle)内容:
, ~# D8 j- d% T- C# Uselect 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_customersfrom 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解决这个问题?
) X0 M9 n9 E: x( q* M结果需要在redshift此外,这是一个简化的问题。实际预期结果包括产品类别和客户类型,乘以所需分区的数量。因此,堆栈unionall汇总不是一个很好的解决方案。- i) }7 C' A% u* e1 `. u
                                                                1 P  S5 n9 j& [: P- z' P
    解决方案:                                                               
9 n, m0 b! o8 k) j1 ?( [' F                                                                2016年的博客文章指出了这个问题,并提供了一个基本的解决方案,谢谢Mark D.- `  `" M: R% L- ]8 q" m; T0 e+ d& R& V
Adams。奇怪的是,我在所有的网络上都找不到,所以我在分享我的解决方案。
4 B9 q! D, ?$ @: U) f- `' ^  D关键见解是dense_rank(),根据相关商品的排名,可以为同一商品提供相同的排名,所以最高排名也是唯一商品的计数。如果你试为我想要的每个分区交换以下内容,那就太糟糕了:
$ S/ l, q8 P  ~3 tdense_rank() over(partition by order_month,traffic_channel order by customer_id)因为你需要最高的排名,你必须查询所有内容,然后从每个排名中选择最大值。匹配外部查询中的分区与子查询中的相应分区很重要。" s  e* ^5 q# l7 A( \+ z
/* 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_customersfrom (        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') =       order by order_month,traffic_channel;笔记max()且dense_rank()必须匹配的分区
9 W8 K4 a5 j% }! @dense_rank()将对null排名值(所有排名都在同一个排名,即最大值)。如果你不想这样做null计数值需要一个case when customer_id is not null then dense_rank() ...etc...,或者,max()如果你知道有空值,你可以从中减去一个。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则