Apache Druid groupBy 查询结果过滤:Having 子句(HavingSpec)完整实战指南
数据库数据分析OLAP大数据实时分析数据仓库后端【免费下载链接】druidApache Druid: a high performance real-time analytics database.项目地址https://gitcode.com/gh_mirrors/druid7/druid点击查看免费下载Having 子句是 Apache Druid 中用于对 groupBy 查询聚合结果做行级过滤的 JSON 对象其语义与 SQL 的HAVING子句等价常用来实现只返回满足聚合值条件的分组这类查询需求。本文以 docs/content/querying/having.md 为主体骨架完整覆盖其全部过滤类型与 JSON 语法并结合 processing 模块下的HavingSpec源码实现、GroupByQuery 查询解析逻辑及对应测试讲透每种过滤器的配置方式、底层比较规则与使用注意事项帮助你在实际查询中正确编写和调试 having 子句。一、Having 子句是什么在 SQL 中WHERE作用于原始行而HAVING作用于聚合后的分组结果。Druid 的 having 子句与之对应它也是一个 JSON 对象通过指定聚合值上的条件决定 groupBy 查询返回哪些行即哪些分组。以 GroupByQuery.java 中的定义为依据having 子句作为 groupBy 查询 JSON 的一个可选顶层属性存在JsonProperty(having) HavingSpec havingSpec,在查询执行阶段Druid 会先完成分组与聚合再对每个结果行调用HavingSpec.eval(Row)判断该行是否满足条件见 GroupByQuery.java只有eval返回true的行才会进入最终结果。也就是说having 过滤发生在聚合之后、limit 截断之前。Druid 通过JsonTypeInfo(use JsonTypeInfo.Id.NAME, property type)以type字段反序列化不同的 having 子句HavingSpec接口HavingSpec.java中注册的全部类型如下type取值对应实现类语义andAndHavingSpec逻辑与orOrHavingSpec逻辑或notNotHavingSpec逻辑非greaterThanGreaterThanHavingSpec聚合值大于给定值lessThanLessThanHavingSpec聚合值小于给定值equalToEqualToHavingSpec聚合值等于给定值dimSelectorDimensionSelectorHavingSpec维度值等于给定值alwaysAlwaysHavingSpec恒真主要用于测试组合filterDimFilterHavingSpec复用任意 Druid 查询过滤器其中always和not对应的NeverHavingSpec、AlwaysHavingSpec被作为组合单元暴露在HavingSpec接口中HavingSpec.NEVER/HavingSpec.ALWAYS见 HavingSpec.java主要用于逻辑组合与测试。下面按类别逐一介绍每种语法的 JSON 写法。二、查询过滤器Query Filter HavingSpectype 为 filter查询过滤器类型的 HavingSpec 允许把任意 Druid 查询过滤器直接用在 having 部分。其语法为{ type : filter, filter : any Druid query filter }例如使用一个 selector 过滤器{ type : filter, filter : { type: selector, dimension : dimension, value : dimension_value } }从源码实现看DimFilterHavingSpec.javafilter属性是必填的构造器通过Preconditions.checkNotNull(dimFilter, filter)校验它会把传入的DimFilter转成ValueMatcher后再对每一行做匹配因此凡是 filters.md 中列出的过滤器类型selector、regex、bound、javascript 等都可在此复用。特别注意__time字段的差异filter类型的 HavingSpec 作用于输出字段名为__time时行为与其他 HavingSpec 不同——它作用于每一行的时间戳而不是名为__time的输出字段。官方文档明确建议避免将输出字段命名为__time未来版本的 Druid 可能会强制执行这一约束。三、数值过滤器Numeric Filters数值过滤器是最简单的 having 子句直接对聚合指标与给定数值做比较同时也可作为更复杂的布尔表达式过滤器的底层基础。示例{ type: greaterThan, aggregation: myAggMetric, value: 100 }其中aggregation指定要比较的聚合指标名即 groupBy 查询中aggregations数组里定义的输出名value为数值。下面介绍三种数值过滤器。3.1 equalTo等于匹配聚合值等于给定值的行{ type: equalTo, aggregation: aggregate_metric, value: numeric_value }等价于 SQL 的HAVING aggregate value。3.2 greaterThan大于匹配聚合值大于给定值的行{ type: greaterThan, aggregation: aggregate_metric, value: numeric_value }等价于 SQL 的HAVING aggregate value。3.3 lessThan小于匹配聚合值小于给定值的行{ type: lessThan, aggregation: aggregate_metric, value: numeric_value }等价于 SQL 的HAVING aggregate value。3.4 数值比较的底层实现三种数值过滤器最终都通过同一个工具类HavingSpecMetricComparatorHavingSpecMetricComparator.java完成比较其规则如下若聚合结果以Long存储则用Longs.compare(long, value.longValue())做整型比较若聚合结果是字符串且完全匹配整型正则[-|]?\dLONG_PAT则按getLongMetric取出的长整型值比较其他情况浮点等统一回退为Floats.compare(float, value.floatValue())的浮点比较。因此当聚合指标值很大超出浮点精度或希望做精确整型比较时Druid 会优先走整型路径避免精度损失。对应的序列化/反序列化与组合行为在 HavingSpecTest.java 中有完整测试覆盖例如GreaterThanHavingSpec(agg, 1.3)、LessThanHavingSpec与NotHavingSpec组合的序列化验证。四、维度选择过滤器Dimension Selector FilterdimSelector类型的 having 子句匹配维度值等于给定值的行{ type: dimSelector, dimension: dimension, value: dimension_value }注意它与数值过滤器不同数值过滤器比较的是聚合指标而dimSelector比较的是分组维度本身。从实现看DimensionSelectorHavingSpec.javadimension为必填属性构造器通过checkNotNull校验可选属性extractionFn用于在比较前对维度值做提取转换未指定时默认使用IdentityExtractionFn恒等变换由于 Druid 支持多值维度eval会遍历该维度行的所有取值任一值经extractionFn提取后与value相等即命中若维度行值为空且value也为 null/空串同样视为命中。因此可以在 having 阶段结合 extraction functions 做大小写归一、正则提取等复杂匹配。五、逻辑表达式过滤器Logical Expression Filters与 SQL 的AND/OR/NOT对应Druid 提供三种逻辑组合器其内部havingSpecs/havingSpec可以嵌套任意本页介绍的其他 having 子句包括再嵌套逻辑组合。5.1 AND{ type: and, havingSpecs: [having clause, having clause, ...] }havingSpecs中的每个子句可以是本页定义的任意 having 子句。从 AndHavingSpec.java 的实现看它是短路求值的遍历子句一旦某个子句eval返回false立即返回false。5.2 OR{ type: or, havingSpecs: [having clause, having clause, ...] }同样支持任意嵌套。对应 OrHavingSpec.java 的实现也是短路求值任一子句eval返回true即整体为true。5.3 NOT{ type: not, havingSpec: having clause }对单个子句的结果取反见 NotHavingSpec.java。5.4 组合示例利用逻辑组合可以写出等价于复杂 SQL 的过滤条件。例如返回count大于 100 且avg_price小于 10 或category等于 book{ type: and, havingSpecs: [ { type: greaterThan, aggregation: count, value: 100 }, { type: or, havingSpecs: [ { type: lessThan, aggregation: avg_price, value: 10 }, { type: dimSelector, dimension: category, value: book } ] } ] }六、完整 groupBy 查询示例把 having 子句放入 groupBy 查询 JSON 的having顶层属性即可对聚合结果过滤。下面是一个完整的查询聚合定义参考 aggregations.mdgroupBy 查询整体结构参考 groupbyquery.md{ queryType: groupBy, dataSource: wikiticker, granularity: day, dimensions: [channel], aggregations: [ {type: count, name: edits}, {type: longSum, name: added, fieldName: added} ], having: { type: and, havingSpecs: [ {type: greaterThan, aggregation: edits, value: 50}, {type: lessThan, aggregation: added, value: 100000} ] }, intervals: [2015-09-12T00:00:00.000Z/2015-09-13T00:00:00.000Z] }该查询按channel分组统计每日编辑次数与新增字符数最终只返回编辑次数大于 50 且新增字符数小于 100000的频道分组效果等价于 SQL 的GROUP BY channel HAVING edits 50 AND added 100000。七、使用注意事项与性能提示线程安全HavingSpec对象本身不是线程安全的javadoc 与 GroupByQuery.java 的applyLimit注释均明确提示不应被多个线程同时使用也不要在两个不同线程中同时累积本方法返回的两个Sequence。DimFilterHavingSpec更是在eval内部通过evalCount自增检查检测并发调用一旦发现并发会抛出IllegalStateException(concurrent eval calls not permitted!)见 DimFilterHavingSpec.java。输出字段命名避免把输出字段命名为__time因为filter类型 HavingSpec 对它存在特殊语义作用于行时间戳而非字段值。比较精度数值比较优先走整型路径见第三节对长整型聚合结果更精确浮点场景则按 float 比较若对精度敏感需在设计聚合时留意。缓存每种 HavingSpec 都实现了getCacheKey()如equalTo为0x3、greaterThan为0x4、lessThan为0x5、dimSelector为0x8、filter为0x9参与查询缓存键的生成因此不同 having 条件会生成不同的缓存条目可放心使用。八、进一步阅读本文主体docs/content/querying/having.md可复用的查询过滤器清单docs/content/querying/filters.mdgroupBy 查询完整结构与其余属性docs/content/querying/groupbyquery.md聚合定义与输出名docs/content/querying/aggregations.mdHavingSpec 接口与类型注册processing/src/main/java/io/druid/query/groupby/having/HavingSpec.java查询解析与执行入口processing/src/main/java/io/druid/query/groupby/GroupByQuery.java序列化与组合行为测试processing/src/test/java/io/druid/query/groupby/having/HavingSpecTest.java赞分享数据库数据分析OLAP大数据实时分析数据仓库后端【免费下载链接】druidApache Druid: a high performance real-time analytics database.项目地址https://gitcode.com/gh_mirrors/druid7/druid点击查看免费下载相关推荐Apache Druid groupBy 查询 Having 子句完全指南聚合后过滤的 JSON 语法与源码实现Apache Druid groupBy 查询 Having 子句完全指南聚合后过滤的 JSON 语法与源码实现 本篇技术指南聚焦 Apache Druid数据库OLAP大数据后端Apache Druid groupBy 查询的 LimitSpec 完全指南排序与结果限制Apache Druid groupBy 查询的 LimitSpec 完全指南排序与结果限制 limitSpec 是 Apache Druid 原生nati数据库OLAP大数据后端Apache Druid 查询指南使用 LimitSpec 对 groupBy 查询结果排序与限量Apache Druid 查询指南使用 LimitSpec 对 groupBy 查询结果排序与限量 limitSpec 是 Apache Druid grou数据库数据分析OLAP大数据实时分析数据仓库后端上一篇react-jsonschema-form中的表单数据处理完成回调下一篇Odyssey Theme如何用 Astro 打造完美 Lighthouse 评分的现代商业网站创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

SMS中文手册实战指南:RMA2地表水模拟从网格到运行

SMS中文手册实战指南:RMA2地表水模拟从网格到运行

简介:这份《SMS中文使用手册》面向水利、水文、环境工程及地表水模拟领域的学习者与工程技术人员,用于解决SMS软件界面陌生、操作流程不熟、建模步骤难以入手等问题,适合从入门到进阶的读者系统查阅。资源为单个PDF文件,压缩包约2…

2026/9/26 0:31:42 阅读更多 →
根号怎么打?电脑手机四种输入方法全攻略

根号怎么打?电脑手机四种输入方法全攻略

1. 为什么“打根号”看起来是个小事,却总有人卡住先说个我自己的真实经历。早几年做课件,要写一道二次根式的例题,我在键盘上找了一圈,发现符号面板里压根没有√这个键,最后只能老老实实打“根号”两个字,再…

2026/9/26 0:28:26 阅读更多 →
WPS自动目录与分节页码设置全攻略:从标题样式到更新域

WPS自动目录与分节页码设置全攻略:从标题样式到更新域

1. 为什么手动敲目录这件事,早晚得换成自动化如果你写过超过二十页的文档,大概率经历过这种崩溃:正文改了三级标题,回头发现目录里的页码全对不上,只能一页一页翻着数,数到眼花还容易错位。更别提那种“目录…

2026/9/23 23:13:37 阅读更多 →

最新新闻

E2E脚本化测试为何比手动更可靠?从原理到Playwright实践

E2E脚本化测试为何比手动更可靠?从原理到Playwright实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/26 6:05:05 阅读更多 →
TI C2000Ware注册机制深度解析:v0.0报错的本质与工程级修复

TI C2000Ware注册机制深度解析:v0.0报错的本质与工程级修复

1. 这不是“装个软件”那么简单:C2000Ware安装失败背后的真实战场你点开CCS(Code Composer Studio),新建一个F28004x工程,刚想调用GPIO_toggle(),编译器就甩给你一行红色报错:“Product c2000wa…

2026/9/26 6:05:05 阅读更多 →
TeamAI-CLI:团队级 AI Agent 中间层工具,让个人 AI 能力变成团队资产

TeamAI-CLI:团队级 AI Agent 中间层工具,让个人 AI 能力变成团队资产

1. 为什么团队需要一个 AI Agent 中间层1.1 从"个人玩具"到"团队资产"的断层我观察到一个很普遍的现象:团队里总有一两个人特别会用 AI。他们电脑上装了一堆 CLI 工具,本地存着几十个精心调教过的 prompt 模板,知道什么任…

2026/9/26 6:05:05 阅读更多 →
工业界面协议与Canvas渲染引擎实践:从DSL到高性能部署

工业界面协议与Canvas渲染引擎实践:从DSL到高性能部署

1. 工业现场为什么需要一套自己的界面协议1.1 从一块"卡死"的触摸屏说起三年前我在一个装配车间做设备数据采集的改造,现场有十几台老式工控机,屏幕分辨率清一色 1024768,跑的是某组态软件做的监控画面。问题出在哪?操作…

2026/9/26 6:05:05 阅读更多 →
Aliens Eye如何判断账号是否存在?ML+30维特征混合检测算法深度剖析

Aliens Eye如何判断账号是否存在?ML+30维特征混合检测算法深度剖析

Aliens Eye如何判断账号是否存在?ML30维特征混合检测算法深度剖析 【免费下载链接】Aliens_eye Hunt down 840 social media accounts using AI 项目地址: https://gitcode.com/gh_mirrors/al/Aliens_eye Aliens Eye 是一款 AI 驱动的用户名账号检测&#xf…

2026/9/26 6:05:05 阅读更多 →
VMware虚拟机安装全攻略:从零搭建Linux开发环境与故障排查

VMware虚拟机安装全攻略:从零搭建Linux开发环境与故障排查

1. 为什么我至今还在用本地虚拟机做开发环境每次带新人,我都会让他们先在本地装一台虚拟机。不是因为我守旧,而是因为本地虚拟机是成本最低、容错率最高的“环境试验田”。你可以在里面随便折腾分区、随便改内核参数、随便装一堆互相冲突的运行时&#x…

2026/9/26 6:04:04 阅读更多 →

日新闻

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、…

2026/9/26 0:00:25 阅读更多 →
学校官网模拟全流程实践:从页面布局到后端接口与部署

学校官网模拟全流程实践:从页面布局到后端接口与部署

如果你正在找一门 Web 大作业的题目,或者刚开始接触 Web 前端开发想做点能拿来展示的东西,“学校官网模拟”几乎是最稳的选择。题目看着简单,但要把导航、新闻列表、轮播 Banner、二级页面、后台数据都串起来,其实已经把前端布局、…

2026/9/26 0:00:25 阅读更多 →
超级玛丽游戏源码C++:从零搭建横版跳跃游戏工程

超级玛丽游戏源码C++:从零搭建横版跳跃游戏工程

简介:这是一份面向游戏开发初学者与C进阶学习者的超级玛丽(超级马里奥)游戏源码,基于C面向对象编程实现,适合想通过经典项目理解游戏主循环、角色类设计、地图关卡加载与物理碰撞检测的读者参考。压缩包共49个文件&…

2026/9/26 0:00:25 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/25 19:27:14 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/25 11:15:26 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/25 20:29:09 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/25 20:29:43 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/25 20:29:31 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/25 19:27:26 阅读更多 →