如何在SQL(PHPMyAdmin)中多表关联获取目标输出?
问题描述
我花了两天时间尝试用SQL和PHPMyAdmin通过三张表获取目标输出,求帮忙,谢谢!
我用了下面的查询语句,但得不到预期结果:
SELECT calender.date, trade_details.client_code, sum(trade_details.net_pnl) as trade_Value, sum(kuber_reports.net_value) as kuber_Value FROM calender LEFT JOIN trade_details ON calender.date = trade_details.trade_Date LEFT JOIN kuber_reports ON calender.date = kuber_reports.trans_Date WHERE trade_details.client_code = 'GBN10001' GROUP BY calender.date, trade_details.client_code;
表结构
Calendar表
| ID | date |
|---|---|
| 1 | 2022-12-13 |
| 2 | 2022-12-14 |
| 3 | 2022-12-15 |
| 4 | 2022-12-16 |
| 5 | 2022-12-17 |
| 6 | 2022-12-18 |
Kuber_reports表
| ID | trans_Date | net_Value | client_code |
|---|---|---|---|
| 1 | 2022-12-14 | 100 | GBN10001 |
| 2 | 2022-12-14 | -50 | GBN10001 |
| 3 | 2022-12-14 | 100 | GBN10001 |
| 4 | 2022-12-15 | 500 | GBN10001 |
| 5 | 2022-12-16 | 1000 | GBN10001 |
trade_details表
| ID | trade_Date | net_pnl | client_code |
|---|---|---|---|
| 1 | 2022-12-14 | 100 | GBN10001 |
| 2 | 2022-12-14 | -50 | GBN10001 |
| 3 | 2022-12-14 | 100 | GBN10001 |
| 4 | 2022-12-15 | 500 | GBN10001 |
| 5 | 2022-12-16 | 900 | GBN10001 |
预期输出
| ID | Calender.date | net_pnl | net_value | client_code | Difference |
|---|---|---|---|---|---|
| 1 | 2022-12-14 | 150 | 150 | GBN10001 | 0 |
| 2 | 2022-12-15 | 500 | 500 | GBN10001 | 0 |
| 3 | 2022-12-16 | 900 | 1000 | GBN10001 | -100 |
解决方案
你的问题出在直接关联三张表会产生笛卡尔积,比如2022-12-14日,trade_details有3条记录,kuber_reports也有3条,关联后会生成9条重复记录,求和时数值会被错误放大。
正确做法是先分别对两张业务表按日期、客户分组求和,再和calendar表关联:
SELECT ROW_NUMBER() OVER(ORDER BY c.date) AS ID, c.date AS `Calender.date`, COALESCE(t.net_pnl, 0) AS net_pnl, COALESCE(k.net_value, 0) AS net_value, 'GBN10001' AS client_code, COALESCE(t.net_pnl, 0) - COALESCE(k.net_value, 0) AS Difference FROM calender c LEFT JOIN ( SELECT trade_Date, SUM(net_pnl) AS net_pnl FROM trade_details WHERE client_code = 'GBN10001' GROUP BY trade_Date ) t ON c.date = t.trade_Date LEFT JOIN ( SELECT trans_Date, SUM(net_Value) AS net_value FROM kuber_reports WHERE client_code = 'GBN10001' GROUP BY trans_Date ) k ON c.date = k.trans_Date WHERE t.net_pnl IS NOT NULL OR k.net_value IS NOT NULL ORDER BY c.date;
关键说明:
- 子查询
t和k先完成单表的分组求和,避免多表关联时的笛卡尔积问题; COALESCE函数处理空值,确保某张表无数据时显示0,避免计算错误;ROW_NUMBER()生成预期输出中的自增ID;WHERE子句过滤无交易数据的日期,只保留有记录的日期;- 最终按日期排序,与预期输出完全匹配。
内容的提问来源于stack exchange,提问作者Santhosh Kumar
相关产品推荐
相关产品推荐

