SQL技术问询:用子查询汇总发票行项目并合并GROUP BY结果
合并税额与商品金额汇总查询的解决方案
嘿,这个问题其实很好解决——用条件聚合就可以把两个查询合并成一个,而且比分开查再合并高效多了!
最优方案:条件聚合
因为你的两个查询基础过滤条件完全一致,只是对ACCT字段的判断不同,所以我们可以在SUM函数里用CASE WHEN来分别统计符合条件的金额,一次扫描数据就能得到所有需要的结果:
SELECT TRANSNUM AS Invoice_Num, -- 汇总所有非税账户的商品金额 SUM(CASE WHEN d.ACCT != 52 THEN d.DAMOUNT ELSE 0 END) AS Total_of_Items, -- 汇总税账户的税额 SUM(CASE WHEN d.ACCT = 52 THEN d.DAMOUNT ELSE 0 END) AS Total_Tax, -- 计算税率,同时处理商品金额为0的异常情况(避免除以0报错) CASE WHEN SUM(CASE WHEN d.ACCT != 52 THEN d.DAMOUNT ELSE 0 END) = 0 THEN NULL ELSE SUM(CASE WHEN d.ACCT = 52 THEN d.DAMOUNT ELSE 0 END) / SUM(CASE WHEN d.ACCT != 52 THEN d.DAMOUNT ELSE 0 END) END AS Tax_Percent FROM DETAIL d JOIN TRANS t ON t.ID = d.ID WHERE d.POSTDATE = '2018-01-01' AND t.type = 6 GROUP BY TRANSNUM ORDER BY TRANSNUM;
为什么这个方案更好?
- 只需要扫描一次
DETAIL和TRANS表,比分开查询再合并的效率更高; - 逻辑更简洁,避免了子查询或表连接带来的额外复杂度;
- 自动处理“只有商品没有税”或“只有税没有商品”的情况,对应的汇总值会显示为
0,税率会根据情况返回NULL(你可以根据需求改成0或其他默认值)。
备选方案:子查询连接
如果你更习惯用子查询的方式合并结果,也可以把两个原始查询作为子表,通过Invoice_Num连接起来:
SELECT t1.Invoice_Num, t1.Total_of_Items, -- 处理没有税额的发票,显示为0 COALESCE(t2.Total_Tax, 0) AS Total_Tax, -- 同样处理除数为0的情况 CASE WHEN t1.Total_of_Items = 0 THEN NULL ELSE COALESCE(t2.Total_Tax, 0) / t1.Total_of_Items END AS Tax_Percent FROM ( -- 商品金额汇总子查询 SELECT TRANSNUM AS Invoice_Num, SUM(DAMOUNT) AS Total_of_Items FROM DETAIL d JOIN TRANS t ON t.ID = d.ID WHERE d.POSTDATE= '2018-01-01' AND t.type=6 AND d.ACCT !=52 GROUP BY TRANSNUM ) t1 LEFT JOIN ( -- 税额汇总子查询 SELECT TRANSNUM AS Invoice_Num, SUM(DAMOUNT) AS Total_Tax FROM DETAIL d JOIN TRANS t ON t.ID = d.ID WHERE d.POSTDATE= '2018-01-01' AND t.type=6 AND d.ACCT =52 GROUP BY TRANSNUM ) t2 ON t1.Invoice_Num = t2.Invoice_Num ORDER BY t1.Invoice_Num;
这个方案的好处是逻辑和你原来的两个查询更贴近,但缺点是需要扫描两次数据表,效率略低于条件聚合方案。
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

