SQL:根据组中的其他列值保留一行

SQL: Keep a single row based on other column values within a group

提问人:teogj 提问时间:11/16/2023 最后编辑:teogj 更新时间:11/17/2023 访问量:44

问:

假设我们有这个表:

user_id order       product
1       1           a
1       2           b
1       3           b
2       1           a
2       2           c
3       1           c
3       2           a
3       3           a

在这个表格中,我的目标是创建一个新表格,该表格旨在为每个唯一表格保留一行,而理想情况下应该显示与每个用户下达的最后一个订单相对应的一行。换言之,预期输出如下所示:user_idproduct

user_id   last_product
1         b
2         c
3         a

到目前为止,我一直在通过语句来回尝试,即使用如下查询,但没有成功:CASE WHEN

SELECT user_id
     , CASE WHEN order = MAX(order) THEN product END AS last_product
FROM table
GROUP BY 1
ORDER BY 1;

理想情况下,我希望在不必使用任何类型的 CTE 的情况下实现这一目标。有没有简单而优雅的解决方案可以做到这一点?

sql snowflake-cloud-data-platform

评论


答:

1赞 SelVazi 11/16/2023 #1

您可以使用窗口功能为分区的每一行分配一个唯一的序列号,然后只选择第一个,订单将分配给每个用户下达的最后一个订单 1。row_number()desc

select user_id, product as last_product
from (
  select *, row_number() over (partition by user_id order by ordr desc) as rn
  from mytable
) as s
where rn = 1
0赞 Dave Welden 11/16/2023 #2

这是 Qualify 的一个很好的用例

select user_id, product as last_product
from t0
qualify row_number() over (
    partition by user_id
    order by order_no desc
) = 1;
USER_ID LAST_PRODUCT
1 b
2 c
3 一个
0赞 Kathmandude 11/17/2023 #3

我想会读得更不言自明last_value()

select distinct 
       user_id,
       last_value(product) over (partition by user_id order by ordr) as last_product
from my_table;

需要记住的一件事是 Snowflake 关于他们实现 last_value() 的说明

如果未指定window_frame,则默认值为整个窗口:

无界前行和无界后行

这与ANSI标准不同,ANSI标准规定了以下内容 窗口框架的默认值:

前一行和当前行之间的范围

您还可以使用顺序列来限定行,就像您在问题中尝试的那样。顺便说一句,这是一个保留关键字,因此我建议使用不同的列名,以防止将来出现意外错误。order

select user_id,
       product as last_product
from my_table
qualify order = max(order) over (partition by user_id);