Mysql 在SELECT中优化子查询

Mysql 在SELECT中优化子查询,mysql,sql,join,query-optimization,innodb,Mysql,Sql,Join,Query Optimization,Innodb,我的表架构如下所示: 索引: products.id主键 产品说明:独特 .id主键 expenses.product\u id product.id的外键 我的目标是加载 当月每种产品的成本作为11月的成本 上个月每种产品的成本为10月份的成本 与上月成本相比,当月成本的变化-上月成本作为成本 当月成本与上个月成本的百分比变化*100/当月成本的百分比差异 我已经成功地编写了SQL代码,它正好做到了这一点: 选择描述,SUMcost-IFNULL 选择总成本 费用 其中月=9,年=2019,产

我的表架构如下所示:

索引:

products.id主键 产品说明:独特 .id主键 expenses.product\u id product.id的外键 我的目标是加载

当月每种产品的成本作为11月的成本 上个月每种产品的成本为10月份的成本 与上月成本相比,当月成本的变化-上月成本作为成本 当月成本与上个月成本的百分比变化*100/当月成本的百分比差异 我已经成功地编写了SQL代码,它正好做到了这一点:

选择描述,SUMcost-IFNULL 选择总成本 费用 其中月=9,年=2019,产品id=e.product\U id 按产品编号分组 ,0作为成本, 总成本*100/ 选择总成本 费用 其中月=9,年=2019,产品id=e.product\U id 按产品编号分组 作为百分比_diff, SUMcost作为10月的成本, IFNULL 选择总成本 费用 其中月=9,年=2019,产品id=e.product\U id 按产品编号分组 ,0作为9月的成本 从费用e 在e.product_id=p.id上加入产品p 其中月=10年=2019年 按产品编号分组 按产品id排序的订单; 但是,将同一子查询复制粘贴三次真的能解决问题吗?理论上,每个产品需要运行四个查询。还有更优雅的方式吗


谢谢你的帮助

您可以一次计算所有月份和所有产品:

SELECT year, month,
       SUM(costs) as curr_month_costs,
       LAG(SUM(costs)) OVER (ORDER BY year, month) as prev_month_costs,
       (SUM(costs) -
        LAG(SUM(costs)) OVER (ORDER BY year, month) 
       ) as diff,
       LAG(SUM(costs)) OVER (ORDER BY year, month) * 100 / SUM(costs)
FROM expenses e JOIN
     products p
     ON e.product_id = p.id
GROUP BY product_id, year, month
ORDER BY year, month, product_id;

如果只想选择当前月份,可以使用子查询。

我将通过条件聚合来解决这个问题:

select 
    p.description,
    sum(case when e.month = 11 then e.cost else 0 end) costs_november,
    sum(case when e.month = 10 then e.cost else 0 end) costs_october,
    sum(case when e.month = 11 then e.cost else -1 * e.cost end) costs,
    sum(case when e.month = 10 then e.cost else 0 end)
        * 100
        / nullif(
            sum(case when e.month = 11 then e.cost else 0 end),
            0
        ) percent_diff
from expenses e
inner join products p on p.id = e.product_id
where e.year = 2019 and e.month in (10, 11)
goup by e.product_id
通过使用子查询,您可以避免重复相同的条件和。无论如何,您的RDBMS可能会对其进行优化,但这会使查询更具可读性:

select 
    description,
    costs_november,
    costs_october,
    costs_november - costs_october costs,
    costs_october * 100 / nullif(costs_november, 0) percent_diff
from (
    select 
        p.description,
        sum(case when e.month = 11 then e.cost else 0 end) costs_november,
        sum(case when e.month = 10 then e.cost else 0 end) costs_october
    from expenses e
    inner join products p on p.id = e.product_id
    where e.year = 2019 and e.month in (10, 11)
    goup by e.product_id
) t

您是否从未有过月内成本变化?请列出您当前拥有的索引。@P.salman费用/成本稍后不会变化。我想我不能使用滞后,因为我仍在使用MySQL 5.7.26