【发布时间】:2020-06-03 17:49:01
【问题描述】:
这个问题主要是关于 PrestoSQL 的旧版本,这些问题已经在(现在更名的)Trino 项目中解决了 346. 然而,亚马逊的 Athena 项目基于 Presto 版本 0.217(Athena 引擎 2)和 0.172(Athena 引擎 1),它们确实存在下述问题。这个问题是专门围绕 Athena Engine 1 / PrestoSQL 版本 0.172 编写的
问题(tl;dr)
- Presto 窗口函数中的
ROWS BETWEEN和RANGE BETWEEN有什么区别?- 这些只是彼此的同义词,还是存在核心概念差异?
- 如果它们只是同义词,为什么
ROWS BETWEEN允许的选项比RANGE BETWEEN多?
- 是否存在可以在
ROWS BETWEEN和RANGE BETWEEN上使用完全相同的参数并获得不同结果的查询场景?- 如果只使用
unbounded/current row,是否存在使用RANGE而不是ROWS(反之亦然)的情况?
- 如果只使用
- 既然
ROWS有更多选项,为什么文档中根本没有提到呢? o_O
评论
presto documentation 甚至对RANGE 都相当安静,并且没有提及ROWS。我没有在 Presto 中找到很多关于窗口函数的讨论或示例。我开始设置 Presto 代码库来尝试解决这个问题。希望有人能把我从这件事中解救出来,我们可以一起改进文档。
Presto 代码有a parser 和test cases 用于ROWS 变体,但有no mention in the documentation 和ROWS。
我发现ROWS 和RANGE 的test cases 没有测试两种语法之间的任何不同。
它们几乎看起来像同义词,但在我的测试中它们的行为确实不同,并且具有不同的 allowed parameters 和 validation rules。
以下示例可以使用运行 Presto 0.213-e-0.1 的 starburstdata/presto Docker 映像运行。通常我通过 Amazon Athena 运行 Presto 0.172,并且几乎总是最终使用 ROWS。
范围
RANGE 似乎仅限于“UNBOUNDED”和“CURRENT ROW”。以下返回错误:
range between 1 preceding and 1 following
use tpch.tiny;
select custkey, orderdate,
array_agg(orderdate) over (
partition by custkey
order by orderdate asc
range between 1 preceding and 1 following
) previous_orders
from orders where custkey in (419, 320) and orderdate < date('1996-01-01')
order by custkey, orderdate asc;
错误:
Window frame RANGE PRECEDING is only supported with UNBOUNDED
以下范围语法可以正常工作(预期不同的结果)。 以下所有示例均基于上述查询,只是更改了范围
range between unbounded preceding and current row
custkey | orderdate | previous_orders
---------+------------+--------------------------------------------------------------------------
320 | 1992-07-10 | [1992-07-10]
320 | 1992-07-30 | [1992-07-10, 1992-07-30]
320 | 1994-07-08 | [1992-07-10, 1992-07-30, 1994-07-08]
320 | 1994-08-04 | [1992-07-10, 1992-07-30, 1994-07-08, 1994-08-04]
320 | 1994-09-18 | [1992-07-10, 1992-07-30, 1994-07-08, 1994-08-04, 1994-09-18]
320 | 1994-10-12 | [1992-07-10, 1992-07-30, 1994-07-08, 1994-08-04, 1994-09-18, 1994-10-12]
419 | 1992-03-16 | [1992-03-16]
419 | 1993-12-29 | [1992-03-16, 1993-12-29]
419 | 1995-01-30 | [1992-03-16, 1993-12-29, 1995-01-30]
range between current row and unbounded following
custkey | orderdate | previous_orders
---------+------------+--------------------------------------------------------------------------
320 | 1992-07-10 | [1992-07-10, 1992-07-30, 1994-07-08, 1994-08-04, 1994-09-18, 1994-10-12]
320 | 1992-07-30 | [1992-07-30, 1994-07-08, 1994-08-04, 1994-09-18, 1994-10-12]
320 | 1994-07-08 | [1994-07-08, 1994-08-04, 1994-09-18, 1994-10-12]
320 | 1994-08-04 | [1994-08-04, 1994-09-18, 1994-10-12]
320 | 1994-09-18 | [1994-09-18, 1994-10-12]
320 | 1994-10-12 | [1994-10-12]
419 | 1992-03-16 | [1992-03-16, 1993-12-29, 1995-01-30]
419 | 1993-12-29 | [1993-12-29, 1995-01-30]
419 | 1995-01-30 | [1995-01-30]
无限前导和无限后继之间的范围
custkey | orderdate | previous_orders
---------+------------+--------------------------------------------------------------------------
320 | 1992-07-10 | [1992-07-10, 1992-07-30, 1994-07-08, 1994-08-04, 1994-09-18, 1994-10-12]
320 | 1992-07-30 | [1992-07-10, 1992-07-30, 1994-07-08, 1994-08-04, 1994-09-18, 1994-10-12]
320 | 1994-07-08 | [1992-07-10, 1992-07-30, 1994-07-08, 1994-08-04, 1994-09-18, 1994-10-12]
320 | 1994-08-04 | [1992-07-10, 1992-07-30, 1994-07-08, 1994-08-04, 1994-09-18, 1994-10-12]
320 | 1994-09-18 | [1992-07-10, 1992-07-30, 1994-07-08, 1994-08-04, 1994-09-18, 1994-10-12]
320 | 1994-10-12 | [1992-07-10, 1992-07-30, 1994-07-08, 1994-08-04, 1994-09-18, 1994-10-12]
419 | 1992-03-16 | [1992-03-16, 1993-12-29, 1995-01-30]
419 | 1993-12-29 | [1992-03-16, 1993-12-29, 1995-01-30]
419 | 1995-01-30 | [1992-03-16, 1993-12-29, 1995-01-30]
行
RANGE 的三个工作示例都适用于ROWS,并产生相同的输出。
rows between unbounded preceding and current row
rows between current row and unbounded following
rows between unbounded preceding and unbounded following
输出省略 - 与上面相同
但是,ROWS 允许更多的控制,因为您也可以执行上述 range 失败的语法:
rows between 1 preceding and 1 following
custkey | orderdate | previous_orders
---------+------------+--------------------------------------
320 | 1992-07-10 | [1992-07-10, 1992-07-30]
320 | 1992-07-30 | [1992-07-10, 1992-07-30, 1994-07-08]
320 | 1994-07-08 | [1992-07-30, 1994-07-08, 1994-08-04]
320 | 1994-08-04 | [1994-07-08, 1994-08-04, 1994-09-18]
320 | 1994-09-18 | [1994-08-04, 1994-09-18, 1994-10-12]
320 | 1994-10-12 | [1994-09-18, 1994-10-12]
419 | 1992-03-16 | [1992-03-16, 1993-12-29]
419 | 1993-12-29 | [1992-03-16, 1993-12-29, 1995-01-30]
419 | 1995-01-30 | [1993-12-29, 1995-01-30]
rows between current row and 1 following
custkey | orderdate | previous_orders
---------+------------+--------------------------
320 | 1992-07-10 | [1992-07-10, 1992-07-30]
320 | 1992-07-30 | [1992-07-30, 1994-07-08]
320 | 1994-07-08 | [1994-07-08, 1994-08-04]
320 | 1994-08-04 | [1994-08-04, 1994-09-18]
320 | 1994-09-18 | [1994-09-18, 1994-10-12]
320 | 1994-10-12 | [1994-10-12]
419 | 1992-03-16 | [1992-03-16, 1993-12-29]
419 | 1993-12-29 | [1993-12-29, 1995-01-30]
419 | 1995-01-30 | [1995-01-30]
rows between 5 preceding and 2 preceding
custkey | orderdate | previous_orders
---------+------------+--------------------------------------------------
320 | 1992-07-10 | NULL
320 | 1992-07-30 | NULL
320 | 1994-07-08 | [1992-07-10]
320 | 1994-08-04 | [1992-07-10, 1992-07-30]
320 | 1994-09-18 | [1992-07-10, 1992-07-30, 1994-07-08]
320 | 1994-10-12 | [1992-07-10, 1992-07-30, 1994-07-08, 1994-08-04]
419 | 1992-03-16 | NULL
419 | 1993-12-29 | NULL
419 | 1995-01-30 | [1992-03-16]
【问题讨论】:
-
range用于定义覆盖the last 6 months之类的内容的窗口,无论包含多少行。但我不知道 Presto。 -
@a_horse_with_no_name 所以听起来其他 SQL 引擎/语法允许
RANGE基于列值,Presto 似乎不支持。如果是这种情况,那么 Presto 应该更倾向于记录ROWS函数,因为这基本上就是它所支持的全部内容。这确实是有道理的——“UNBOUNDED”在两种情况下都是一样的。 -
sqlitetutorial.net/sqlite-window-functions/sqlite-window-frame SQLite 的这个解释也非常符合 Presto 的使用行为。
-
只是想插话并感谢您的体贴、勤奋和对本文清晰度的承诺。这是我们在拼命寻找 SO 时都希望找到的“宝石”之一。赞一个!
标签: window-functions amazon-athena presto trino