多供应商付款同比百分比差异SQL查询问题求助
嘿,我来帮你搞定这个供应商付款同比百分比差异的问题!根据你描述的需求,我假设你用的是标准SQL(如果是MySQL、PostgreSQL这类特定数据库,我可以再调整细节),下面是具体的实现思路和可直接复用的代码:
供应商付款同比增长计算方案
首先,核心思路是用**窗口函数LAG()**来获取每个供应商上一年的付款金额——它能帮我们把“去年的付款额(old)”和“今年的付款额(new)”放在同一行,完美适配你((new-old)/old)*100的计算需求。
第一步:先匹配上一年的付款数据
假设你的表名为vendor_payments,字段包含company_name(供应商名称)、payment_year(付款年份)、total_payment(当年总付款额),先写基础查询来关联上一年的数据:
SELECT company_name, payment_year, total_payment, -- 按供应商分组、年份升序,取上一行的付款额(即去年的金额) LAG(total_payment) OVER (PARTITION BY company_name ORDER BY payment_year) AS previous_year_payment FROM vendor_payments ORDER BY company_name, payment_year;
第二步:计算同比百分比(处理异常情况)
接下来基于上面的子查询,套用公式计算同比,同时要处理两种容易报错的场景:
- 供应商第一年的数据,没有上一年参考值,同比设为0%
- 上一年付款额为0,避免除以0报错,同比也设为0%(你也可以根据需求改成
NULL)
完整的最终查询代码:
SELECT company_name, payment_year, CONCAT('$', total_payment) AS formatted_payment, -- 格式化金额为带$的样式 CASE -- 无上年数据或上年付款为0时返回0% WHEN previous_year_payment IS NULL OR previous_year_payment = 0 THEN '0%' -- 正常计算同比,保留整数(可调整ROUND的第二个参数控制小数位数) ELSE CONCAT(ROUND(((total_payment - previous_year_payment) / previous_year_payment) * 100, 0), '%') END AS yoy_growth FROM ( SELECT company_name, payment_year, total_payment, LAG(total_payment) OVER (PARTITION BY company_name ORDER BY payment_year) AS previous_year_payment FROM vendor_payments ) AS subquery ORDER BY company_name, payment_year;
实际结果示例(和你期望的一致)
执行后会得到类似这样的输出:
| company_name | payment_year | formatted_payment | yoy_growth |
|---|---|---|---|
| Company A | 2015 | $400 | 0% |
| Company A | 2016 | $400 | 0% |
| Company A | 2017 | $800 | 100% |
| Company B | 2014 | $200 | 0% |
针对月度存储数据的调整
如果你是按月存储明细数据,但需要按年计算同比,只需要先按月数据聚合成年度总付款,再套上面的逻辑即可:
-- 先把月度数据聚合为年度总付款 WITH annual_payments AS ( SELECT company_name, EXTRACT(YEAR FROM payment_month) AS payment_year, -- 假设payment_month是日期类型 SUM(total_payment) AS total_payment FROM vendor_payments GROUP BY company_name, EXTRACT(YEAR FROM payment_month) ) -- 再计算同比 SELECT company_name, payment_year, CONCAT('$', total_payment) AS formatted_payment, CASE WHEN previous_year_payment IS NULL OR previous_year_payment = 0 THEN '0%' ELSE CONCAT(ROUND(((total_payment - previous_year_payment) / previous_year_payment) * 100, 0), '%') END AS yoy_growth FROM ( SELECT company_name, payment_year, total_payment, LAG(total_payment) OVER (PARTITION BY company_name ORDER BY payment_year) AS previous_year_payment FROM annual_payments ) AS subquery ORDER BY company_name, payment_year;
要是运行代码还有报错,你可以把具体错误信息告诉我,我再帮你针对性排查~
内容的提问来源于stack exchange,提问作者confusedquery
相关产品推荐
相关产品推荐

