欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > Doris 中聚合函数使用常见问题及解决方案

Doris 中聚合函数使用常见问题及解决方案

2025/4/24 15:04:27 来源:https://blog.csdn.net/qq_41924536/article/details/147426511  浏览:    关键词:Doris 中聚合函数使用常见问题及解决方案

目录

问题描述

示例数据表结构

orders 表结构

order_details 表结构

初始查询

问题分析

解决方案

修改后的查询

主要修改点

确保所有列都是聚合函数的结果:

总结


在使用 Doris 进行数据分析时,聚合函数是不可或缺的一部分。然而,由于 Doris 的特定优化和语法要求,有时会遇到一些常见的问题,导致查询无法正确执行或返回预期结果。本文将介绍一个常见的聚合函数使用问题,并提供解决方案。

问题描述

假设我们有一个业务场景,需要统计某个时间段内的订单数量,并且需要包含一些额外的统计信息,如超期订单和重办订单的数量。我们希望在查询结果中包含这些统计信息,并且确保这些统计信息不会被重复累加。

示例数据表结构

假设有两个表:orders 和 order_details。

orders 表存储订单的基本信息。

order_details 表存储订单的详细信息,包括订单状态和处理状态。

orders 表结构

字段名

类型

描述

order_id

bigint

订单ID

create_tim

datetime

创建时间

status

int

订单状态

order_details 表结构

字段名

类型

描述

order_id

bigint

订单ID

detail_id

bigint

详情ID

process_state

int

处理状态

is_overdue

int

是否超期

is_renewal

int

是否重办

初始查询

我们希望统计某个时间段内的订单数量,并包含超期订单和重办订单的数量。初始查询如下:


SELECT SUM(CASE WHEN o.status = 1 THEN 1 ELSE 0 END) AS order_cnt_supervised, SUM(CASE WHEN o.status = 0 THEN 1 ELSE 0 END) AS order_cnt_not_supervised, SUM(CASE WHEN o.status = 1 THEN 1 ELSE 0 END) + SUM(CASE WHEN o.status = 0 THEN 1 ELSE 0 END) AS order_cnt_should_supervised, CONCAT(IFNULL(ROUND(SUM(CASE WHEN o.status = 1 THEN 1 ELSE 0 END) * 100.0 / (SUM(CASE WHEN o.status = 1 THEN 1 ELSE 0 END) + SUM(CASE WHEN o.status = 0 THEN 1 ELSE 0 END)), 2), 0), '%') AS supv_rate, CONCAT(IFNULL(ROUND(SUM(CASE WHEN o.status = 0 THEN 1 ELSE 0 END) * 100.0 / (SUM(CASE WHEN o.status = 1 THEN 1 ELSE 0 END) + SUM(CASE WHEN o.status = 0 THEN 1 ELSE 0 END)), 2), 0), '%') AS not_supv_rate, od.overdue_cnt AS order_cnt_overdue, od.renewal_cnt AS order_cnt_renewal 
FROM orders o 
LEFT JOIN (SELECT order_id, SUM(CASE WHEN is_overdue = 1 THEN 1 ELSE 0 END) AS overdue_cnt, SUM(CASE WHEN is_renewal = 1 THEN 1 ELSE 0 END) AS renewal_cnt FROM order_details GROUP BY order_id
) od ON o.order_id = od.order_id 
WHERE o.create_time BETWEEN '2023-01-01 00:00:00' AND '2023-01-31 23:59:59';
问题分析

上述查询在 MySQL 中可以正常执行,但在 Doris 中会报错。具体错误信息可能类似于:ERROR 1055 (42000): Expression #6 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'od.overdue_cnt' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

这个问题的原因是 Doris 对 GROUP BY 子句有更严格的要求。在 Doris 中,所有非聚合列都必须包含在 GROUP BY 子句中,或者所有列都必须是聚合函数的结果。

解决方案

为了解决这个问题,我们可以使用 MAX() 聚合函数来确保 overdue_cnt 和 renewal_cnt 只被使用一次,避免重复累加。

修改后的查询

SELECT SUM(CASE WHEN o.status = 1 THEN 1 ELSE 0 END) + MAX(od.overdue_cnt) + MAX(od.renewal_cnt) AS order_cnt_supervised, SUM(CASE WHEN o.status = 0 THEN 1 ELSE 0 END) AS order_cnt_not_supervised, SUM(CASE WHEN o.status = 1 THEN 1 ELSE 0 END) + SUM(CASE WHEN o.status = 0 THEN 1 ELSE 0 END) + MAX(od.overdue_cnt) + MAX(od.renewal_cnt) AS order_cnt_should_supervised, CONCAT(IFNULL(ROUND((SUM(CASE WHEN o.status = 1 THEN 1 ELSE 0 END) + MAX(od.overdue_cnt) + MAX(od.renewal_cnt)) * 100.0 / (SUM(CASE WHEN o.status = 1 THEN 1 ELSE 0 END) + SUM(CASE WHEN o.status = 0 THEN 1 ELSE 0 END) + MAX(od.overdue_cnt) + MAX(od.renewal_cnt)), 2), 0), '%') AS supv_rate, CONCAT(IFNULL(ROUND(SUM(CASE WHEN o.status = 0 THEN 1 ELSE 0 END) * 100.0 / (SUM(CASE WHEN o.status = 1 THEN 1 ELSE 0 END) + SUM(CASE WHEN o.status = 0 THEN 1 ELSE 0 END) + MAX(od.overdue_cnt) + MAX(od.renewal_cnt)), 2), 0), '%') AS not_supv_rate, MAX(od.overdue_cnt) AS order_cnt_overdue, MAX(od.renewal_cnt) AS order_cnt_renewal 
FROM orders o 
LEFT JOIN (SELECT order_id, SUM(CASE WHEN is_overdue = 1 THEN 1 ELSE 0 END) AS overdue_cnt, SUM(CASE WHEN is_renewal = 1 THEN 1 ELSE 0 END) AS renewal_cnt FROM order_details GROUP BY order_id
) od ON o.order_id = od.order_id 
WHERE o.create_time BETWEEN '2023-01-01 00:00:00' AND '2023-01-31 23:59:59';
主要修改点

使用 MAX() 聚合函数:

MAX(od.overdue_cnt) AS order_cnt_overdue

MAX(od.renewal_cnt) AS order_cnt_renewal

这样可以确保 overdue_cnt 和 renewal_cnt 只被使用一次,避免重复累加。

确保所有列都是聚合函数的结果:

SUM(CASE WHEN o.status = 1 THEN 1 ELSE 0 END) + MAX(od.overdue_cnt) + MAX(od.renewal_cnt) AS order_cnt_supervised

SUM(CASE WHEN o.status = 0 THEN 1 ELSE 0 END) AS order_cnt_not_supervised

SUM(CASE WHEN o.status = 1 THEN 1 ELSE 0 END) + SUM(CASE WHEN o.status = 0 THEN 1 ELSE 0 END) + MAX(od.overdue_cnt) + MAX(od.renewal_cnt) AS order_cnt_should_supervised

MAX(od.overdue_cnt) AS order_cnt_overdue

MAX(od.renewal_cnt) AS order_cnt_renewal

总结

在 Doris 中使用聚合函数时,需要注意以下几点:

数据类型匹配:确保过滤条件中的数据类型与表中的数据类型匹配。

聚合函数要求:确保所有非聚合列都包含在 GROUP BY 子句中,或者所有列都必须是聚合函数的结果。

使用 MAX() 聚合函数:在某些情况下,使用 MAX() 可以避免重复累加问题,同时保持数据的准确性。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词