在 window 函数的 FILTER 子句中引用当前行
Referencing current row in FILTER clause of window function
在 PostgreSQL 9.4 中,window 函数有新的选项 FILTER
到 select window 处理框架。该文档提到了它,但没有提供示例。在线搜索会产生一些示例,包括来自 2ndQuadrant 的示例,但我发现的所有示例都是带有常量表达式的相当琐碎的示例。我正在寻找的是一个包含当前行值的过滤器表达式。
假设我有一个 table 和一堆列,其中一个是 date
类型:
col1 | col2 | dt
------------------------
1 | a | 2015-07-01
2 | b | 2015-07-03
3 | c | 2015-07-10
4 | d | 2015-07-11
5 | e | 2015-07-11
6 | f | 2015-07-13
...
在整个 table 上处理 date
的 window 定义很简单:WINDOW win AS (ORDER BY dt)
我想知道当前行之前的 4 天(含)内有多少行。所以我想生成这个输出:
col1 | col2 | dt | count
--------------------------------
1 | a | 2015-07-01 | 1
2 | b | 2015-07-03 | 2
3 | c | 2015-07-10 | 1
4 | d | 2015-07-11 | 3
5 | e | 2015-07-11 | 3
6 | f | 2015-07-13 | 4
...
window 函数的 FILTER
子句似乎是显而易见的选择:
count(*) FILTER (WHERE <b>current_row.dt</b> - dt <= 4) OVER win
但是如何指定 current_row.dt
(因为缺少更好的语法)?这可能吗?
如果这不可能,是否有其他方法可以在 window 框架中 selecting date
范围?框架规范没有帮助,因为它都是基于行的。
我对使用子查询的替代解决方案不感兴趣,它必须基于window处理。
您实际上并未聚合 行,因此新的聚合FILTER
子句不是正确的工具。 window 函数更像它,但问题仍然存在:window 的 frame definition 不能依赖于 值 当前行。它只能计算 ROWS
子句之前或之后的给定行数。
要实现这一点,请将每天的计数和 LEFT JOIN
汇总到范围内的一整套天数。然后你可以应用一个window函数:
SELECT t.*, ct.ct_last4days
FROM (
SELECT *, sum(ct) OVER (ORDER BY dt ROWS 3 PRECEDING) AS ct_last4days
FROM (
SELECT generate_series(min(dt), max(dt), interval '1 day')::date AS dt
FROM tbl t1
) d
LEFT JOIN (SELECT dt, count(*) AS ct FROM tbl GROUP BY 1) t USING (dt)
) ct
JOIN tbl t USING (dt);
在寡妇框架定义中省略 ORDER BY dt
通常 有效,因为顺序是从子查询中的 generate_series()
继承而来的。但是 SQL 标准在没有显式 ORDER BY
的情况下没有任何保证,它可能会中断更复杂的查询。
相关:
- Select finishes where athlete didn't finish first for the past 3 events
- PostgreSQL: running count of rows for a query 'by minute'
- PostgreSQL unnest() with element number
我认为表达式中没有任何表示 "current row" 的语法。 postgres 的 gram.y 文件创建了一个过滤子句
只取一个 a_expr,这只是普通的表达式子句。那里
不特定于 window 函数或表达式中的过滤子句。
据我所知,window 子句中唯一的当前行概念是用于指定 window 帧边界。我不认为这让你
你想要什么。
您可能会从封闭的查询中获得一些吸引力:
http://www.postgresql.org/docs/current/static/sql-expressions.html
When an aggregate expression appears in a subquery (see Section 4.2.11
and Section 9.22), the aggregate is normally evaluated over the rows
of the subquery. But an exception occurs if the aggregate's arguments
(and filter_clause if any) contain only outer-level variables: the
aggregate then belongs to the nearest such outer level, and is
evaluated over the rows of that query.
但我不太清楚。
在 PostgreSQL 9.4 中,window 函数有新的选项 FILTER
到 select window 处理框架。该文档提到了它,但没有提供示例。在线搜索会产生一些示例,包括来自 2ndQuadrant 的示例,但我发现的所有示例都是带有常量表达式的相当琐碎的示例。我正在寻找的是一个包含当前行值的过滤器表达式。
假设我有一个 table 和一堆列,其中一个是 date
类型:
col1 | col2 | dt ------------------------ 1 | a | 2015-07-01 2 | b | 2015-07-03 3 | c | 2015-07-10 4 | d | 2015-07-11 5 | e | 2015-07-11 6 | f | 2015-07-13 ...
在整个 table 上处理 date
的 window 定义很简单:WINDOW win AS (ORDER BY dt)
我想知道当前行之前的 4 天(含)内有多少行。所以我想生成这个输出:
col1 | col2 | dt | count -------------------------------- 1 | a | 2015-07-01 | 1 2 | b | 2015-07-03 | 2 3 | c | 2015-07-10 | 1 4 | d | 2015-07-11 | 3 5 | e | 2015-07-11 | 3 6 | f | 2015-07-13 | 4 ...
window 函数的 FILTER
子句似乎是显而易见的选择:
count(*) FILTER (WHERE <b>current_row.dt</b> - dt <= 4) OVER win
但是如何指定 current_row.dt
(因为缺少更好的语法)?这可能吗?
如果这不可能,是否有其他方法可以在 window 框架中 selecting date
范围?框架规范没有帮助,因为它都是基于行的。
我对使用子查询的替代解决方案不感兴趣,它必须基于window处理。
您实际上并未聚合 行,因此新的聚合FILTER
子句不是正确的工具。 window 函数更像它,但问题仍然存在:window 的 frame definition 不能依赖于 值 当前行。它只能计算 ROWS
子句之前或之后的给定行数。
要实现这一点,请将每天的计数和 LEFT JOIN
汇总到范围内的一整套天数。然后你可以应用一个window函数:
SELECT t.*, ct.ct_last4days
FROM (
SELECT *, sum(ct) OVER (ORDER BY dt ROWS 3 PRECEDING) AS ct_last4days
FROM (
SELECT generate_series(min(dt), max(dt), interval '1 day')::date AS dt
FROM tbl t1
) d
LEFT JOIN (SELECT dt, count(*) AS ct FROM tbl GROUP BY 1) t USING (dt)
) ct
JOIN tbl t USING (dt);
在寡妇框架定义中省略 ORDER BY dt
通常 有效,因为顺序是从子查询中的 generate_series()
继承而来的。但是 SQL 标准在没有显式 ORDER BY
的情况下没有任何保证,它可能会中断更复杂的查询。
相关:
- Select finishes where athlete didn't finish first for the past 3 events
- PostgreSQL: running count of rows for a query 'by minute'
- PostgreSQL unnest() with element number
我认为表达式中没有任何表示 "current row" 的语法。 postgres 的 gram.y 文件创建了一个过滤子句 只取一个 a_expr,这只是普通的表达式子句。那里 不特定于 window 函数或表达式中的过滤子句。 据我所知,window 子句中唯一的当前行概念是用于指定 window 帧边界。我不认为这让你 你想要什么。
您可能会从封闭的查询中获得一些吸引力:
http://www.postgresql.org/docs/current/static/sql-expressions.html
When an aggregate expression appears in a subquery (see Section 4.2.11 and Section 9.22), the aggregate is normally evaluated over the rows of the subquery. But an exception occurs if the aggregate's arguments (and filter_clause if any) contain only outer-level variables: the aggregate then belongs to the nearest such outer level, and is evaluated over the rows of that query.
但我不太清楚。