Mysql 优化复杂SQL查询-避免经常运行子查询

Mysql 优化复杂SQL查询-避免经常运行子查询,mysql,optimization,Mysql,Optimization,我写了一个非常低效的查询,我拼命想从中获得最好的性能。 (我的MySQL技能不是很好,所以在阅读的时候请放纵一下…) 首先:我只能以只读方式访问数据库。所以不幸的是,我没有办法创建临时表(我认为这是一个很好的解决方案) 我查询的目标是列出每一篇文章(表格艺术),同时将过去三年的销售数量作为单独的列显示在右侧。 所有文件标题均列在“dok”中,所有行项目均列在“pos”中 以下是表格结构(仅提及相关字段): 艺术: 身份证件重量;价格 杜克: 身份证件日期 pos: 身份证件杜克迪德;艺术设计;数

我写了一个非常低效的查询,我拼命想从中获得最好的性能。 (我的MySQL技能不是很好,所以在阅读的时候请放纵一下…)

首先:我只能以只读方式访问数据库。所以不幸的是,我没有办法创建临时表(我认为这是一个很好的解决方案)

我查询的目标是列出每一篇文章(表格艺术),同时将过去三年的销售数量作为单独的列显示在右侧。 所有文件标题均列在“dok”中,所有行项目均列在“pos”中

以下是表格结构(仅提及相关字段):

艺术: 身份证件重量;价格

杜克: 身份证件日期

pos: 身份证件杜克迪德;艺术设计;数量;数量

为了简单起见,所有的表名都被修改了,真正的表和字段都有非常复杂的名称

我的第一次尝试是(三个子查询):

这是非常低效的

因此,我编写了一个查询,给出了以下结果集(并非所有文章都包含在内,因为并非所有文章都已售出):

工艺标识、年份、数量

将其用作表左键联接,如下所示:

select art.id,
art.weight,
art.price,
t1.qty,
t2.qty,
t3.qty

from (art)

left join (select art.id, year(dok.date) as yr, sum(pos.qty) as qty from pos inner join dok on pos.dok_id = dok.id inner join art on pos.art_id = art.id where year(dok.date) in >= 2013 group by art.id, year(dok.date)) t1 on t1.id = art.id
left join (select art.id, year(dok.date) as yr, sum(pos.qty) as qty from pos inner join dok on pos.dok_id = dok.id inner join art on pos.art_id = art.id where year(dok.date) in >= 2013 group by art.id, year(dok.date)) t2 on t2.id = art.id
left join (select art.id, year(dok.date) as yr, sum(pos.qty) as qty from pos inner join dok on pos.dok_id = dok.id inner join art on pos.art_id = art.id where year(dok.date) in >= 2013 group by art.id, year(dok.date)) t3 on t3.id = art.id

where t1.yr= 2013 and t2.yr= 2014 and t3.yr= 2015;
这个查询只持续了第一个查询的大约50%。这是更好的,但不如我认为它可以得到利用你们一些人的想法好。 将子查询用作表的性能更好,但我认为它仍在使用三次

有没有办法让MySQL只执行一次子查询,将其用于所有三个连接? 还是有完全不同的方法

我期待着你的想法

来自德国的问候


Stefan

您可以使用单个子查询,在SUM中使用IF只对该字段中特定年份行的值进行求和。类似这样(未经测试):-


什么是表格模式?您可以加入预聚合的结果集(您的第二种方法)一次,然后使用
MAX(如果(year=xxx,…)
在不同的列中选择不同的年份。@Vatev您能进一步解释一下吗?我想我不明白这会做什么…@AG21这些是表格的相关列:art:id;重量;price-dok:id;日期;pos:id;杜克迪德;艺术设计;数量(见上面的帖子,我在中编辑过)如果你用“t1”替换“t2”和“t3”,它就像一个符咒!非常感谢你!持续时间约为原始查询的10%!
select art.id,
art.weight,
art.price,
t1.qty,
t2.qty,
t3.qty

from (art)

left join (select art.id, year(dok.date) as yr, sum(pos.qty) as qty from pos inner join dok on pos.dok_id = dok.id inner join art on pos.art_id = art.id where year(dok.date) in >= 2013 group by art.id, year(dok.date)) t1 on t1.id = art.id
left join (select art.id, year(dok.date) as yr, sum(pos.qty) as qty from pos inner join dok on pos.dok_id = dok.id inner join art on pos.art_id = art.id where year(dok.date) in >= 2013 group by art.id, year(dok.date)) t2 on t2.id = art.id
left join (select art.id, year(dok.date) as yr, sum(pos.qty) as qty from pos inner join dok on pos.dok_id = dok.id inner join art on pos.art_id = art.id where year(dok.date) in >= 2013 group by art.id, year(dok.date)) t3 on t3.id = art.id

where t1.yr= 2013 and t2.yr= 2014 and t3.yr= 2015;
SELECT art.id,
    art.weight,
    art.price,
    t1.qty_2013,
    t1.qty_2014,
    t1.qty_2015
FROM (art)
LEFT JOIN 
(
    SELECT art.id, 
            SUM(IF(year(dok.date) = 2013, pos.qty, 0)) AS qty_2013
            SUM(IF(year(dok.date) = 2014, pos.qty, 0)) AS qty_2014
            SUM(IF(year(dok.date) = 2015, pos.qty, 0)) AS qty_2015
    FROM pos 
    INNER JOIN dok ON pos.dok_id = dok.id 
    INNER JOIN art ON pos.art_id = art.id 
    WHERE YEAR(dok.date) IN (2013, 2014, 2015)
    GROUP BY art.id
) t1 ON t1.id = art.id