MySQL查询需求:按余额类型聚合客户并按规则排序拼接
问题描述
现有transactions表,包含customer(客户)、debit(借方)、credit(贷方)字段,表数据如下:
| 客户 | 借方 | 贷方 |
|---|---|---|
| a | 70 | 50 |
| a | 100 | 20 |
| a | 20 | 60 |
| b | 100 | 20 |
| b | 40 | 80 |
| b | 10 | 30 |
| c | 100 | 200 |
| c | 100 | 30 |
| c | 80 | 90 |
| d | 100 | 200 |
| d | 90 | 30 |
| d | 80 | 90 |
| e | 100 | 100 |
| e | 100 | 30 |
| e | 80 | 90 |
需求
- 计算每个客户的余额:
SUM(debit) - SUM(credit) - 判断余额类型
bal_type:余额>0为positive,否则为negative - 按
bal_type分组,将同组客户按规则排序后拼接成字符串:positive组:按余额降序排列negative组:按余额升序排列
尝试的SQL语句
SELECT CASE WHEN (SUM(debit)-SUM(credit))<0 THEN "negative" ELSE "positive" END AS bal_type, customer FROM transactions GROUP BY customer
当前输出
| bal_type | 客户 |
|---|---|
| positive | a |
| positive | b |
| negative | c |
| negative | d |
| positive | e |
期望输出
| bal_type | 客户 |
|---|---|
| positive | e,a,b |
| negative | c,d |
解决方案
MySQL/MariaDB 版本
SELECT bal_type, GROUP_CONCAT(customer ORDER BY balance DESC SEPARATOR ',') AS 客户 FROM ( SELECT customer, SUM(debit) - SUM(credit) AS balance, CASE WHEN SUM(debit) - SUM(credit) > 0 THEN 'positive' ELSE 'negative' END AS bal_type FROM transactions GROUP BY customer ) t GROUP BY bal_type ORDER BY bal_type DESC;
PostgreSQL 版本
SELECT bal_type, STRING_AGG(customer, ',' ORDER BY CASE bal_type WHEN 'positive' THEN balance DESC ELSE balance ASC END) AS 客户 FROM ( SELECT customer, SUM(debit) - SUM(credit) AS balance, CASE WHEN SUM(debit) - SUM(credit) > 0 THEN 'positive' ELSE 'negative' END AS bal_type FROM transactions GROUP BY customer ) t GROUP BY bal_type ORDER BY bal_type DESC;
说明
- 子查询先计算每个客户的余额和对应的
bal_type - 外层查询按
bal_type分组,使用字符串聚合函数(GROUP_CONCAT/STRING_AGG),并在聚合时指定排序规则:positive组按余额降序排列客户negative组按余额升序排列客户
内容的提问来源于stack exchange,提问作者Prasad Sanap
相关产品推荐
相关产品推荐

