获得每个分区第一条记录的最佳方法:FIRST_VALUE与ROW_NUMBER

问题描述

我正在寻找使用sql获取每个分区(a,b)的第一条记录(a,b,c列)的最快方法。表格大约有10、000、000行。

方法1:

SELECT * FROM (
    SELECT a,b,c,ROW_NUMBER() OVER ( PARTITION by a,b ORDER BY date DESC) as row_num
    FROM T 
) WHERE row_num =1

但是它可能在幕后做额外的工作-每个分区只需要第一行。

使用FirsT_VALUE()方法#2。由于FirsT_VALUE()返回表达式 让我们使用一些分隔符将a,b,c打包/连接成单个表达式,例如:

SELECT FirsT_VALUE(a+','+'b'+','+c) 
OVER ( PARTITION by a,b ORDER BY date  DESC rows unbounded preceding) FROM T

但是在这种情况下,我需要解压缩结果,这是额外的步骤。

使用FirsT_VALUE()方法#3-对a,b重复OVER(...):

SELECT 
FirsT_VALUE(a) 
OVER ( PARTITION by a,b ORDER BY date  DESC rows unbounded preceding),FirsT_VALUE(b) 
OVER ( PARTITION by a,c 
FROM T

方法3中,我不知道数据库引擎(Redshift)是否足够聪明以至于只能分区一次

解决方法

这个评论太长了。

第一个查询与其他两个查询不同。第一个仅返回每组一行。其他两个返回与原始查询相同的行。

您应该使用满足您需求的版本,我认为这是第一个。如果将select distinctgroup by添加到其他查询中,则可能会增加开销,从而使它们变慢-但您可以测试数据以查看是否正确。

您的直觉是正确的,即第一个查询做了不必要的工作。在完全支持索引的数据库中,相关子查询通常更快。但是,我不认为Redshift会是这种情况。