ROWS、RANGE、GROUPS(窗口帧子句)
适用于 ✅ 开源版 ✅ 专业版 ✅ 企业版
当窗口规范包含 ORDER BY 子句 时,窗口帧可以是显式的或隐式的,对于 聚合窗口函数。简而言之,窗口帧限制了窗口的大小,从当前行开始双向限制。
例如
- 累积和可以通过将窗口框架设置为包含所有
PRECEDING
行来实现。 - 滑动平均值可以通过将窗口框架设置为包含一定数量的
PRECEDING
行以及FOLLOWING
行来实现。
帧可以在 3 种模式下限制
-
ROWS
:这通过确切的行数来限制帧,类似于 LIMIT 子句。例如,ROWS 3 PRECEDING
将包括窗口中的 3 个前导行和当前行。 -
RANGE
:这通过值范围在逻辑上限制帧,例如RANGE 3 PRECEDING
将包括[当前值 - 3, 当前值]
的值范围和窗口中的当前行。这仅适用于具有明确定义范围的类型,包括数值和时间类型。 -
GROUPS
:这通过不同的值计数范围在逻辑上限制帧,例如GROUPS 3 PRECEDING
将包括包含 3 个前导不同值的行和窗口中的当前行。
请注意,在上面的示例中,默认情况下总是包含当前行。可以使用窗口排除子句将其排除。
完整语法
最好使用语法来说明完整的语法
在上面仅提供单个 frameBound
的简短形式中(例如 ROWS 3 PRECEDING
),则暗示 ROWS BETWEEN frameBound AND CURRENT ROW
。
示例
再次最好用例子解释
SELECT ID, PUBLISHED_IN, -- The 2 preceding rows and the current row COUNT(*) OVER (ORDER BY PUBLISHED_IN ROWS 2 PRECEDING), -- The 42 preceding years and the current row COUNT(*) OVER (ORDER BY PUBLISHED_IN RANGE 42 PRECEDING), -- The 1 preceding groups of years and the current row trunc(PUBLISHED_IN, -1), COUNT(*) OVER (ORDER BY trunc(PUBLISHED_IN, -1) GROUPS 1 PRECEDING) FROM BOOK ORDER BY published_in
create.select( BOOK.ID, BOOK.PUBLISHED_IN, // The 2 preceding rows and the current row count().over(orderBy(BOOK.PUBLISHED_IN).rowsPreceding(2)), // The 42 preceding years and the current row count().over(orderBy(BOOK.PUBLISHED_IN).rangePreceding(42)), // The 1 preceding groups of years and the current row trunc(BOOK.PUBLISHED_IN, -1), count().over(orderBy(trunc(BOOK.PUBLISHED_IN, -1)) .groupsPreceding(1))) .from(BOOK) .orderBy(BOOK.PUBLISHED_IN) .fetch();
产生
+----+--------------+-------+-------+-------+--------+ | id | published_in | rows | range | decade | groups | +----+--------------+------+-------+--------+--------+ | 2 | 1945 | 1 | 1 | 1940 | 2 | | 1 | 1948 | 2 | 2 | 1940 | 2 | | 3 | 1988 | 3 | 2 | 1980 | 3 | | 4 | 1990 | 3 | 3 | 1990 | 2 | +----+--------------+------+-------+--------+--------+
正如你可以看到的
-
ROWS
:所有行都有 0 到 2 个前导行,加上当前行。 -
RANGE
:虽然1990
在 42 年内有 2 个前导行(加上与当前行具有相同值的行),但其他年份在该时间跨度内的行数较少。 -
GROUPS
:1980
年代有 2 行属于前一个 10 年组(加上与当前行具有相同值的行)。
这当然需要一些练习。虽然 ROWS
子句很简单,但 RANGE
和 GROUPS
子句有点难以理解,尽管它们更强大。
如果您省略帧子句,但有一个 ORDER BY 子句,则RANGE UNBOUNDED PRECEDING
帧对于 聚合窗口函数是隐式的。如果没有ORDER BY
,则RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
是隐式的,即整个窗口分区。
方言支持
此示例使用 jOOQ
count().over(orderBy(BOOK.ID).rowsPreceding(3))
翻译成以下特定方言的表达式
Aurora Postgres, BigQuery, ClickHouse, CockroachDB, DB2, Databricks, DuckDB, Exasol, Firebird, H2, Informix, MariaDB, MemSQL, MySQL, Oracle, Postgres, Redshift, SQLDataWarehouse, SQLServer, SQLite, Snowflake, Sybase, Teradata, Trino, Vertica, YugabyteDB
count(*) OVER ( ORDER BY BOOK.ID ROWS 3 PRECEDING )
ASE、Access、Aurora MySQL、Derby、HSQLDB、Hana
/* UNSUPPORTED */
使用 jOOQ 3.21 生成。早期 jOOQ 版本的支持可能有所不同。 在我们的网站上翻译您自己的 SQL
反馈
您对此页面有任何反馈吗?我们很乐意听到!