SQL/Presto:有多个条件的排名(一个条件是检查行是否在同一个标签中)
SQL/Presto: rank with multiple conditions (one condition is checking if rows is in the same tag)
我有如下数据 (dt):
group_id customer_id tag score phase
1 a l1 0 2020
1 b l2 0 2021
2 a l4 1 2019
2 e l3 1 2019
2 d l3 1 2018
3 q 1 2020
3 w 1 2019
3 z l5 1 2019
3 x l5 1 2019
3 c l6 1 2019
我想
- 在一组中对他们进行排名,首先按分数(分数越低越好)
- 然后连接 customer_id 如果 2 位客户在同一组且得分相同,标签相同(非空)
- 我需要按阶段对它们进行排名(首选较旧的阶段)以生成最终列表。
因此,所需的输出是:
group_id customer_id tag score phase rank
1 a l1 0 2020 1
1 b l2 0 2021 2
2 a l4 1 2019 2
2 e,d l3 1 2019, 2018 1
3 q 1 2020 2
3 w 1 2019 1
3 z,x l5 1 2019, 2019 1
3 c l6 1 2019 1
我已经编写了以下查询,但我不确定如何合并检查标签中是否有 2 个客户的条件并进一步添加阶段比较条件。
SELECT group_id, customer_id, tag, score, phase,
RANK() OVER (PARTITION BY group_id ORDER BY score) AS temp_rank
FROM dt
我用 ROW_NUMBER()
而不是 RANK()
。以下查询 returns 你想要的输出。我用 sql 测试了这个查询。在内置子查询中,我按 tag
分组,并使用 STRING_AGG()
函数将相同的值放入列中。然后我将结果加入到主 table.
select t.group_id,t.customer_id,t.tag,t.score,t.phase,ROW_NUMBER() OVER (PARTITION BY t.group_id ORDER BY t.score) AS rank
from
(select distinct t1.*,t2.group_id,t2.score
from
(SELECT tag, STRING_AGG(customer_id, ',') AS customer_id,STRING_AGG(phase, ',') AS phase
FROM dt
group by tag) t1 join dt t2 on t1.tag = t2.tag) t
order by t.group_id,t.customer_id
结果 sql:https://dbfiddle.uk/sql
postgre 中的结果sql:https://dbfiddle.uk/postgresql
您必须 group by group_id, tag, score
并使用 array_join(array_agg())
连接 customer_id
和 phase
用于具有非 NULL 标记的行。
然后对带有 NULL 标记的行使用 UNION ALL
。
然后使用 RANK()
而不是 DENSE_RANK()
window 函数:
SELECT group_id, customer_id, tag, score, phase,
DENSE_RANK() OVER (PARTITION BY group_id ORDER BY score, min_phase) temp_rank
FROM (
SELECT group_id,
array_join(array_agg(customer_id), ',') customer_id,
tag,
score,
array_join(array_agg(phase), ',') phase,
MIN(phase) min_phase
FROM dt
WHERE tag IS NOT NULL
GROUP BY group_id, tag, score
UNION ALL
SELECT group_id, customer_id, tag, score, phase, phase
FROM dt
WHERE tag IS NULL
) t
参见 demo(对于 Postgresql)。
结果:
group_id
customer_id
tag
score
phase
temp_rank
1
a
l1
0
2020
1
1
b
l2
0
2021
2
2
e,d
l3
1
2019,2018
1
2
a
l4
1
2019
2
3
w
null
1
2019
1
3
c
l6
1
2019
1
3
z,x
l5
1
2019,2019
1
3
q
null
1
2020
2
我有如下数据 (dt):
group_id customer_id tag score phase
1 a l1 0 2020
1 b l2 0 2021
2 a l4 1 2019
2 e l3 1 2019
2 d l3 1 2018
3 q 1 2020
3 w 1 2019
3 z l5 1 2019
3 x l5 1 2019
3 c l6 1 2019
我想
- 在一组中对他们进行排名,首先按分数(分数越低越好)
- 然后连接 customer_id 如果 2 位客户在同一组且得分相同,标签相同(非空)
- 我需要按阶段对它们进行排名(首选较旧的阶段)以生成最终列表。
因此,所需的输出是:
group_id customer_id tag score phase rank
1 a l1 0 2020 1
1 b l2 0 2021 2
2 a l4 1 2019 2
2 e,d l3 1 2019, 2018 1
3 q 1 2020 2
3 w 1 2019 1
3 z,x l5 1 2019, 2019 1
3 c l6 1 2019 1
我已经编写了以下查询,但我不确定如何合并检查标签中是否有 2 个客户的条件并进一步添加阶段比较条件。
SELECT group_id, customer_id, tag, score, phase,
RANK() OVER (PARTITION BY group_id ORDER BY score) AS temp_rank
FROM dt
我用 ROW_NUMBER()
而不是 RANK()
。以下查询 returns 你想要的输出。我用 sql 测试了这个查询。在内置子查询中,我按 tag
分组,并使用 STRING_AGG()
函数将相同的值放入列中。然后我将结果加入到主 table.
select t.group_id,t.customer_id,t.tag,t.score,t.phase,ROW_NUMBER() OVER (PARTITION BY t.group_id ORDER BY t.score) AS rank
from
(select distinct t1.*,t2.group_id,t2.score
from
(SELECT tag, STRING_AGG(customer_id, ',') AS customer_id,STRING_AGG(phase, ',') AS phase
FROM dt
group by tag) t1 join dt t2 on t1.tag = t2.tag) t
order by t.group_id,t.customer_id
结果 sql:https://dbfiddle.uk/sql
postgre 中的结果sql:https://dbfiddle.uk/postgresql
您必须 group by group_id, tag, score
并使用 array_join(array_agg())
连接 customer_id
和 phase
用于具有非 NULL 标记的行。
然后对带有 NULL 标记的行使用 UNION ALL
。
然后使用 RANK()
而不是 DENSE_RANK()
window 函数:
SELECT group_id, customer_id, tag, score, phase,
DENSE_RANK() OVER (PARTITION BY group_id ORDER BY score, min_phase) temp_rank
FROM (
SELECT group_id,
array_join(array_agg(customer_id), ',') customer_id,
tag,
score,
array_join(array_agg(phase), ',') phase,
MIN(phase) min_phase
FROM dt
WHERE tag IS NOT NULL
GROUP BY group_id, tag, score
UNION ALL
SELECT group_id, customer_id, tag, score, phase, phase
FROM dt
WHERE tag IS NULL
) t
参见 demo(对于 Postgresql)。
结果:
group_id | customer_id | tag | score | phase | temp_rank |
---|---|---|---|---|---|
1 | a | l1 | 0 | 2020 | 1 |
1 | b | l2 | 0 | 2021 | 2 |
2 | e,d | l3 | 1 | 2019,2018 | 1 |
2 | a | l4 | 1 | 2019 | 2 |
3 | w | null | 1 | 2019 | 1 |
3 | c | l6 | 1 | 2019 | 1 |
3 | z,x | l5 | 1 | 2019,2019 | 1 |
3 | q | null | 1 | 2020 | 2 |