注册
布尔聚合函数在不同数据库(达梦、PostgreSQL、MySQL)中的用法对比与测试报告
专栏/技术分享/ 文章详情 /

布尔聚合函数在不同数据库(达梦、PostgreSQL、MySQL)中的用法对比与测试报告

何处惹尘埃 2026/09/18 174 0 0
摘要

一、 测试背景与目的

本报告主要验证在达梦(DM)、PostgreSQL(PG)和 MySQL 数据库中,实现“全部为真”(BOOL_AND / EVERY)和“存在为真”(BOOL_OR)逻辑的用法,并展示测试过程及结果。同时,针对测试中出现的输出顺序差异进行底层原理分析。

二、 通用测试数据准备

为统一测试标准,三个数据库均使用如下建表和数据插入语句(根据各库语法特性有微小调整):

-- 创建测试表 CREATE TABLE tasks ( user_id INT, task_name TEXT, is_completed BOOLEAN ); -- 插入测试数据 INSERT INTO tasks VALUES (1, 'Task A', TRUE), (1, 'Task B', FALSE), (2, 'Task C', TRUE), (2, 'Task D', TRUE), (3, 'Task E', NULL);

注:数据逻辑为 User 1 有完成和未完成;User 2 全部完成;User 3 状态未知(NULL)。

三、 各数据库实现方式及测试结果

1. 达梦数据库 (DM)

达梦遵循 PostgreSQL 标准,原生支持 EVERY、BOOL_AND 和 BOOL_OR。其中 EVERY 是 BOOL_AND 的别名,两者功能完全一致。

测试 SQL:

SELECT user_id, EVERY(is_completed) AS all_completed, -- 或使用 BOOL_AND(is_completed) BOOL_OR(is_completed) AS any_completed FROM tasks GROUP BY user_id;

输出结果(达梦):

user_id all_completed any_completed
1 false true
2 true true
3 null null

注:达梦支持直接显示 true/false/null 字面量。


2. PostgreSQL (PG)

PostgreSQL 是这些函数的原始来源,原生支持 BOOL_AND、BOOL_OR 以及别名 EVERY。

测试 SQL:

SELECT user_id, BOOL_AND(is_completed) AS all_completed, BOOL_OR(is_completed) AS any_completed FROM tasks GROUP BY user_id;

输出结果(PostgreSQL):

user_id all_completed any_completed
2 t t
1 f t
3 null null

注:PG 默认用 t 代表 True,f 代表 False。且此时输出顺序被打乱,为 2, 1, 3。


3. MySQL

MySQL 不支持 EVERY、BOOL_AND 和 BOOL_OR 函数。因为 MySQL 中布尔类型实质是 TINYINT(1)(False 为 0,True 为 1),通常使用聚合函数 MIN() 和 MAX() 来完美平替。

替代原理:

  • MIN(is_completed) 等价于 EVERY / BOOL_AND:只要组内有一个 0(假),最小值就是 0;只有全为 1(真),最小值为 1。
  • MAX(is_completed) 等价于 BOOL_OR:只要组内有一个 1(真),最大值就是 1。

测试 SQL:

SELECT user_id, MIN(is_completed) AS all_completed, MAX(is_completed) AS any_completed FROM tasks GROUP BY user_id ORDER BY user_id; -- 此处为了展示清晰,显式加了排序

输出结果(MySQL):

user_id all_completed any_completed
1 0 1
2 1 1
3 NULL NULL

注:MySQL 显示为 0 和 1,若想看 true/false 可在外层嵌套 IF 函数转换。

四、 为什么达梦和 PostgreSQL 的输出顺序不一样?

在上述没有显式排序的测试中,达梦的输出顺序是 1, 2, 3,而 PostgreSQL 的输出顺序是 2, 1, 3。这是因为 SQL 标准中规定:只要没有显式使用 ORDER BY 子句,数据库是不保证返回结果顺序的,顺序是随机的。

底层原因在于查询优化器在处理 GROUP BY 时,使用了不同的算法:

  1. 达梦数据库(排序聚合 Sort Aggregation):达梦通常先将数据按照 user_id 进行物理排序,然后再进行聚合。因此结果会自然呈现为升序的 1, 2, 3。
  2. PostgreSQL(哈希聚合 Hash Aggregation):为了提高性能,PG 默认倾向于将分组键(user_id)进行哈希计算放入内存中的哈希桶。哈希桶的排列顺序由哈希值决定,而不是插入顺序或数字大小,因此打乱了顺序,出现了 2, 1, 3。

解决方案:
为了保证在任何数据库下结果顺序一致且符合预期,必须在 SQL 语句结尾加上 ORDER BY user_id。这也是 DBA 和开发人员在编写报表或测试数据时应当遵循的标准规范。

-- 正确且规范的写法: SELECT user_id, MIN(is_completed) AS all_completed, MAX(is_completed) AS any_completed FROM tasks GROUP BY user_id ORDER BY user_id;
评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服