根据 Snowflake 中某一列的值最大来选择一条记录

问题描述 投票:0回答:4

假设我有一个这样结构的表格

姓名 分数
迈克 40
迈克 79
迈克 49

我只想返回迈克得分为 79 的行,而不返回其他内容。

我一直在使用的代码如下所示:

SELECT Name, COUNT(Name), greatest(Score) FROM
table GROUP BY Name, Score

我尝试了一些不同的变体,例如使用 Rank 和最伟大的函数,但运气不佳。任何帮助将不胜感激,谢谢。

sql snowflake-cloud-data-platform rank
4个回答
2
投票

不确定为什么其他答案使事情变得复杂,你只是想使用 max 函数,如下所示:

WITH data(name, score) as (
    select * from values
    ('Mike', 40),
    ('Mike', 79),
    ('Mike', 79)
)

select name, max(score) as score
from data 
where name ='Mike' group by name;

您的询问:

SELECT Name, COUNT(*), max(Score) FROM
table GROUP BY Name
从功能角度来看,

greatest
与 max “类似”,但正如您所提到的,它不起作用,这是因为它的签名 - 它并不意味着接收单个 expr 作为输入。我建议您阅读最大和最大之间的差异,以确保您完全理解它们。


1
投票

使用 QUALIFY 和 RANK/ROW_NUMBER:

SELECT *
FROM tab
QUALIFY RANK() OVER(PARTITION BY Name ORDER BY Score DESC) = 1

1
投票

详细解释:

如果您向更改后的数据添加 ROW_NUMBERRANK

WITH data(name, score, extra) as (
    select * from values
    ('Mike', 40, 'a'),
    ('Mike', 79, 'b'),
    ('Mike', 79, 'c')
)
select *
    ,row_number() over (partition by name order by score desc) as rn
    ,rank() over (partition by name order by score desc) as rank
from data;
姓名 得分 额外 RN 排名
迈克 79 b 1 1
迈克 79 c 2 1
迈克 40 a 3 3

您可以看到 ROW_NUMBER 只会将值 1 分配给一个值,其中 RANK 将为您提供保留该位置的尽可能多的值,并且在稀疏 RANK 的情况下会有间隙,因为

Mike,40
是第三个值。因此,RANK/ROW_NUMBER 之间的选择取决于您想要如何处理结果以及您是否要加入此数据等。

然后你可以用经典的 ANSI 形式进行过滤:

WITH data(name, score, extra) as (
    select * from values
    ('Mike', 40, 'a'),
    ('Mike', 79, 'b'),
    ('Mike', 79, 'c')
)
select name, score, extra
from (
    select *
        ,row_number() over (partition by name order by score desc) as rn
    from data
)
where rn = 1;

请注意,这是一种不稳定的排序,因为数据库可以返回 Mike,79,b 或 Mike,79,c,但使用 ROW_NUMBER 您只会得到一个。

Snowflake 具有 QUALIFY 命令,允许删除子选择,并在分组完成后运行另一个过滤器。

所以你可以写:

select *
    ,row_number() over (partition by name order by score desc) as rn
from data
QUALIFY rn = 1;
姓名 得分 额外 RN
迈克 79 b 1

但是如果您不想看到 ROW_NUMBER 值,可以将其移至 QUALIFY,并且范围时间与查询完全相同,但这使事情变得更整洁:

WITH data(name, score, extra) as (
    select * from values
    ('Mike', 40, 'a'),
    ('Mike', 79, 'b'),
    ('Mike', 79, 'c')
)
select *
from data
QUALIFY row_number() over (partition by name order by score desc) = 1;
姓名 得分 额外
迈克 79 b

0
投票
© www.soinside.com 2019 - 2024. All rights reserved.