Postgres - 在分组行中使用 window 函数

Postgres - Using window function in grouped rows

根据 https://www.postgresql.org/docs/9.4/queries-table-expressions.html#QUERIES-WINDOW 的 Postgres 文档,它指出

If the query contains any window functions (...), these functions are evaluated after any grouping, aggregation, and HAVING filtering is performed. That is, if the query uses any aggregates, GROUP BY, or HAVING, then the rows seen by the window functions are the group rows instead of the original table rows from FROM/WHERE.

我不明白“那么 window 函数看到的行是组行,而不是来自 FROM/WHERE 的原始 table 行”。请允许我用一个例子来解释我的疑问:

使用这个准备 运行 下面的例子

with cte as ( 
  select 1 as primary_id, 1 as foreign_id, 10 as begins
  union
  select 2 as primary_id, 1 as foreign_id, 20 as begins
  union
  select 3 as primary_id, 1 as foreign_id, 30 as begins
  union
  select 4 as primary_id, 2 as foreign_id, 40 as begins
)
select foreign_id, count(*) over () as window_rows_count, count(*) as grouped_rows_count
from cte
group by foreign_id  

您可能会注意到结果是

所以如果“window 函数看到的行是组行”.. 那么 ¿ 为什么 window_rows_count 返回的值与 grouped_rows_count 不同?

如果从查询中删除 window 函数:

select foreign_id, count(*) as grouped_rows_count
from cte
group by foreign_id

结果,正如预期的那样:

> foreign_id | grouped_rows_count
> ---------: | -----------------:
>          1 |                  3
>          2 |                  1

并且在这个有 2 行的结果上,如果您还应用 window 函数 count(*) over(),它将 return 2,因为它计算了结果集的所有行因为 over 子句是空的,没有任何 partition.

您应该关注 post 上的最后一条评论。 为了进行更多分析,您可以处理以下查询:

with cte as ( 


select 1 as primary_id, 1 as foreign_id, 10 as begins
  union
  select 2 as primary_id, 1 as foreign_id, 20 as begins
  union
  select 3 as primary_id, 1 as foreign_id, 30 as begins
  union
  select 4 as primary_id, 2 as foreign_id, 40 as begins
)
select foreign_id, count(*) over (PARTITION BY foreign_id) as window_rows_count, count(*) as grouped_rows_count
from cte
group by foreign_id ;

这次您会看到每个外国 ID 都占 1 行。 在 url 处查看有关 postgres 的文档: https://www.postgresql.org/docs/13/tutorial-window.html

window函数作用于前面查询得到的整个集合。