当前位置: 首页 > news >正文

【SQL】COUNT... FILTER 的适用场景

【SQL】COUNT... FILTER 的适用场景

  • 一、引言
  • 二、FILTER 基础学习
    • 2.1 语法解析
    • 2.2 适用范围
      • 2.2.1 主流数据库支持情况
    • 2.3 技术优势
      • 2.3.1 性能优化
      • 2.3.2 等阶写法对比
    • 2.4 适用场景
      • 2.4.1 多维统计报表
      • 2.4.2 动态数据过滤
      • 2.4.3 复杂条件处理
  • 三、总结

一、引言

  • 今天参加业务评审,见到一个不太一样的SQL如下,在数据分析与数据库查询场景中,​条件计数常用 CASE WHEN 实现,但 COUNT(*) FILTER (WHERE …) 很少见,觉得比较新奇。
  • 由于日常大量使用的是Hive和Mysql偏多,随着业务场景变更,逐渐使用PostgreSQL多起来,便好奇的想了解这种写法,做个学习笔记。
  • 本文将探讨交流其核心原理、适用场景及技术优势,帮助开发者优化查询性能并提升代码可读性。
# 突然感觉不常见的一种写法
SELECT count(*) FILTER (where s_type='0'),"s"   FROM log_detail
WHERE ds = '20250414'   GROUP BY "s"

二、FILTER 基础学习

2.1 语法解析

COUNT(*) FILTER (WHERE <condition>) 
  • ​**COUNT(*)**​:统计所有行数(包括 NULL 值)。
  • ​**FILTER (WHERE )**​:动态过滤参与计数的记录,仅保留满足条件的行。
  • 示例如上面提到的业务案例;

2.2 适用范围

  • 主要适用于【遵循 SQL:2003 标准或支持扩展聚合函数语法的数据库系统】,具体支持的 SQL 类型及场景如下:

2.2.1 主流数据库支持情况

  • PostgreSQL 及兼容生态​、衍生系统如 ​Greenplum、Amazon Redshift​ 等也兼容该语法。
  • ​SparkSQL​ 会自动将 COUNT(DISTINCT) 转换为 FILTER 表达式以提高性能。
    • 例如,多列去重统计时,Spark 会通过 Expand 操作生成 gid 标记,再结合 FILTER 分条件聚合。
  • SQLite​:支持 FILTER 子句,常用于分组后按条件聚合。
  • 部分 OLAP 引擎​:ClickHouse、Doris​ 等列式存储数据库支持类似语法。

对于日常不使用上述数据库标准的同学,当个参考即可。

2.3 技术优势

2.3.1 性能优化

  • 减少计算冗余​:传统 CASE WHEN 需要遍历所有行并生成中间结果,而 FILTER 子句通过预过滤直接跳过无关数据内存和 CPU 消耗(实测性能提升可达 20%-30%)
  • 优化执行计划​:数据库引擎可针对过滤条件生成更优的索引扫描路径(如 Bitmap Index Scan)。

2.3.2 等阶写法对比

​使用 FILTER 的写法传统 CASE WHEN 写法
​COUNT(*) FILTER (WHERE s_type=‘0’)COUNT(CASE WHEN s_type=‘0’ THEN 1 END)
SUM(amount) FILTER (WHERE status=‘paid’)SUM(CASE WHEN status=‘paid’ THEN amount ELSE 0 END)

2.4 适用场景

2.4.1 多维统计报表

  • 单次查询生成多维度聚合指标,例如:
SELECT  product_category
       ,COUNT(*) FILTER (WHERE region='North') AS north_orders
       ,COUNT(*) FILTER (WHERE region='South') AS south_orders
FROM sales
GROUP BY product_category;

2.4.2 动态数据过滤

  • 结合时间窗口或动态参数实现灵活查询:
-- 统计近7天活跃用户中 VIP 占比
SELECT  COUNT(*) FILTER (WHERE is_vip = true) / COUNT(*)::FLOAT AS vip_ratio
FROM users
WHERE last_login >= CURRENT_DATE - INTERVAL '7 days'

2.4.3 复杂条件处理

  • 支持嵌套子查询和窗口函数,例如:
SELECT  user_id
       ,COUNT(*) FILTER (WHERE s_type = '1' 
                   AND EXISTS (SELECT 1 FROM A WHERE ad_id = B.ad_id)
                  ) AS clicks
FROM B
GROUP BY user_id;

三、总结

COUNT(*) FILTER (WHERE …) 通过语法精简与执行优化,显著提升了条件统计的效率与可维护性。尤其在 PostgreSQL 和 Spark 生态中,是多维分析的推荐实践,对于需兼容传统数据库的场景,可通过 CASE WHEN 平稳过渡即可。

相关文章:

  • 大模型在直肠癌诊疗全流程预测及应用研究报告
  • 已开源!CMU提出NavRL :基于强化学习的无人机自主导航和动态避障新方案
  • Threejs 奇幻几何体:边缘、线框、包围盒大冒险
  • 深入剖析 RocketMQ 中的 MappedFile 技术
  • 使用MCP服务通过自然语言操作数据库(vscode+cline版本)
  • [极客大挑战 2019]PHP 1
  • AI改变生活
  • 苍穹外卖day04
  • JPG同步删除RAW批处理文件
  • Vue ‘v-model‘ directives require the attribute value which is valid as LHS.
  • 八、自动化函数
  • 单基因高低分组和相关基因的GSEA等富集分析教程,代做分析
  • dev中使用auto的方法
  • AETTA: Label-Free Accuracy Estimation for Test-Time Adaptation
  • python编程-实现非确定性有限自动机
  • 正弦波有效值和平均值(学习笔记)
  • 探秘Transformer系列之(27)--- MQA GQA
  • 【一篇关于自我刷题的思考】
  • 使用Python进行AI图像生成:从GAN到风格迁移的完整指南
  • 如何安装git?
  • “两高”发布侵犯知产犯罪司法解释:降低部分犯罪入罪门槛
  • 泽连斯基提议乌俄“立即、全面和无条件”停火
  • 郑庆华任同济大学党委书记
  • 从“龙队”到“龙副”,国乒这批退役球员为何不爱当教练了
  • 上海市闵行区原二级巡视员琚汉铮接受纪律审查和监察调查
  • 京东美团商战,能惠及骑手吗?