PostgreSQL 9.4 引入特性:WITHIN GROUP 和 FILTER 子句

PostgreSQL9.4引入了WITHIN GROUP和FILTER子句,增强了SQL标准。WITHIN GROUP子句简化了使用窗口函数对有序子集执行聚集函数的过程,适用于percentile_cont(), percentile_disc(), mode()等有序集聚合函数。FILTER子句允许在聚集函数中添加过滤条件,提高查询效率。例如,通过WITHIN GROUP子句计算数据的四分位数,通过FILTER子句区分奇数和偶数的计数。这些新特性提高了代码可读性和查询性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PostgreSQL 9.4扩展SQL标准,增加了两个新的子句:WITHIN GROUP 和 FILTER 。

WITHIN GROUP 子句

WITHIN GROUP 对有序子集执行聚集函数非常有用。PostgreSQL9.0 版本引入窗口函数用于关联数据子集和其对应每个记录,针对任何特定记录定义一组聚集,利用 OVER(PARTITION BY/ORDER BY) 子句分组执行聚集函数。

使用PostgreSQL 9.4 版本的 WITHIN GROUP 子句可以简化之前使用窗口函数聚集有序子集数据实现的功能。

percentile_cont(), percentile_disc() 计算百分位数;mode()计算有序集的众数;rank(), dense_rank(), percent_rank(), cume_dist() 可以和WITHIN GROUP 子句一起使用。

并不是所有聚集函数都可以和WITHIN GROUP 子句一起使用。我们可以通过查询pg_aggregate 表的aggkind 字段进行识别,它包括三个值:

  • n 表示正常聚集函数,如 max, min等
  • o 表示有序集聚集函数
  • h 表示假设集聚集函数,是有序集的子集
test=# SELECT aggfnoid, aggkind
test-#    FROM pg_aggregate
test-#    WHERE aggkind IN ('o', 'h');
          aggfnoid          | aggkind
----------------------------+---------
 pg_catalog.percentile_disc | o
 pg_catalog.percentile_cont | o
 pg_catalog.percentile_cont | o
 pg_catalog.percentile_disc | o
 pg_catalog.percentile_cont | o
 pg_catalog.percentile_cont | o
 mode                       | o
 pg_catalog.rank            | h
 pg_catalog.percent_rank    | h
 pg_catalog.cume_dist       | h
 pg_catalog.dense_rank      | h
(11 行记录)

下面通过示例来说明使用with group的优势。

假设我们需要查询1~20共20个数的四分位数。之前的做法使用OVER (PARTITION BY/ORDER BY)子句把数据分成4个组,然后对每个有序子组求其最大值,使用CTE:

CREATE TABLE t AS SELECT generate_series(1,20) AS val;
 WITH subset AS (
    SELECT val,
       ntile(4) OVER (ORDER BY val) AS tile
    FROM t
  )
  SELECT max(val)
  FROM subset GROUP BY tile ORDER BY tile;

   max
  ------
   5
  10
  15
  20
 (4 rows)

使用PostgreSQL 9.4新的特性可以非常简单,且可读性更好。

$ CREATE TABLE t AS SELECT generate_series(1,20) AS val;

$ SELECT unnest(percentile_disc(array[0.25,0.5,0.75,1])
    WITHIN GROUP (ORDER BY val))
  FROM t;

   max
  ------
   5
  10
  15
  20
 (4 rows)

FILTER子句

filter 子句可以对聚集函数增加过滤功能,仅对符合条件的子集进行聚集。假设我们对一组数据执行count统计,同时需要统计奇数和偶数。我们可以在一个查询中使用filter进行实现:

test=# SELECT count(*) count_all,
test-#          count(*) FILTER(WHERE value % 2=1) count_1,
test-#          count(*) FILTER(WHERE value % 2=0) count_2
test-#   FROM generate_series(1,100,1) as t(value);

 count_all | count_1 | count_2
-----------+---------+---------
       100 |      50 |      50
(1 行记录)

上述实现非常简单,不仅提升了代码可读性,也提升了查询性能。

总结

通过引入这些新子句对SQL标准的扩展可开发人员效率,因为可将更多对数据子集的操作和聚合委托给数据库。通过WITHIN GROUP子句结合使用新的窗口函数,可以更方便管理有序数据子集。

通过使用WITHIN GROUP子句,通过引入新的窗口函数,可以更容易地管理可以排序的数据子集。FILTER子句帮助过滤满足某些条件的数据子集,从而避免不必要的聚合函数。

SQL中,WITHIN GROUP子句用于指定在聚合函数中对组内的顺序进行排序。 [1这个子句通常与聚合函数一起使用,例如listagg函数。listagg函数可以将多行合并成一行,并且可以在合并过程中指定排序顺序。在WITHIN GROUP子句中,可以使用ORDER BY子句来对组内的数据进行排序。这样,生成的合并结果就可以按照指定的顺序进行排列。在这个例子中,我们使用了ORDER BY子句来指定按照组的顺序进行排序。最后,我们得到了每个组的最大值,按照组的顺序排列的结果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Oracle函数 --聚合函数中的语法within group](https://blog.csdn.net/richieruan/article/details/54314576)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [oracle的 listagg() WITHIN GROUP () 行转列函数的使用](https://blog.csdn.net/sinat_36257389/article/details/81004843)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [PostgreSQL 9.4 引入特性WITHIN GROUP FILTER 子句](https://blog.csdn.net/neweastsun/article/details/116764660)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值