Ben*_*ier 7 sql postgresql aggregate-functions amazon-redshift
我有以下表格:
顾客
customer_id name
----------------
1 bob
2 alice
3 tim
Run Code Online (Sandbox Code Playgroud)
购买
id customer_id item_bought
--------------------------
1 1 hat
2 1 shoes
3 2 glasses
3 2 glasses
4 2 book
5 3 shoes
6 1 hat
Run Code Online (Sandbox Code Playgroud)
我想跟随结果:
customer_name item_bought_most_often
------------------------------------
bob hat
alice glasses
tim shoes
Run Code Online (Sandbox Code Playgroud)
我会这样做(实际上没有尝试,只是想法):
SELECT customer.name as customer_name,
MODE(item_bought) as item_bought_most_ofen
FROM customers
INNER JOIN purchases USING (customer_id)
GROUP_BY customer_id
Run Code Online (Sandbox Code Playgroud)
但是,Redshift中不存在MODE聚合功能.
似乎Redshift用户定义的函数只是常规的标量函数,而不是聚合函数.所以我认为我自己无法定义它.
任何解决方法?
您可以先COUNT每个人购买,然后使用RANK()窗口函数:
SELECT name AS customer_name, item_bought AS item_bought_most_often
FROM(SELECT name,item_bought,RANK() OVER(PARTITION BY name ORDER BY cnt DESC) rnk
FROM (SELECT c.name, p.item_bought, COUNT(*) AS cnt
FROM customers c
JOIN purchases p
ON p.customer_id = c.customer_id
GROUP BY c.name, p.item_bought) AS s1) AS s2
WHERE rnk = 1;
Run Code Online (Sandbox Code Playgroud)
输出:
??????????????????????????????????????????
? customer_name ? item_bought_most_often ?
??????????????????????????????????????????
? alice ? glasses ?
? bob ? hat ?
? tim ? shoes ?
? zoe ? pencil ?
? zoe ? book ?
??????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
笔记:
RANK 将处理多个最常见的值。
编辑:
正如Lukas Eder提到的,它可以进一步简化:
SELECT name AS customer_name, item_bought AS item_bought_most_often
FROM(SELECT name,item_bought,
RANK() OVER(PARTITION BY name ORDER BY COUNT(*) DESC) rnk
FROM customers c
JOIN purchases p
ON p.customer_id = c.customer_id
GROUP BY c.name, p.item_bought) AS s2
WHERE rnk = 1;
Run Code Online (Sandbox Code Playgroud)
您可以mode()使用row_number()以下方式模仿:
select name, item_bought
from (select c.name, p.item_bought, count(*) as cnt,
row_number() over (order by count(*) desc) as seqnum
from customers c join
purchases p
using (customer_id)
group by c.name, p.item_bought
) cp
where seqnum = 1;
Run Code Online (Sandbox Code Playgroud)