我写了一个非常低效的查询,我拼命想要从中获得最佳性能。 (我的MySQL技能不是很好,所以请在阅读时放纵......)
首先:我只对数据库进行只读访问。所以不幸的是,我无法创建临时表(我认为这是一个很好的解决方案)。
我的查询的目标是列出每篇文章(表格),同时将过去三年的销售数量列为右侧的单独列。 所有dokument标题都列在“dok”中,所有行项目都列在“pos”中。
这些是表格结构(仅提及相关字段):
技术: ID;重量;价格; ...
DOK: ID;日期; ...
POS: ID; dok_id; art_id;数量; ...
为简单起见,所有表名都被更改,真实表和字段的名称非常复杂。
我的第一次尝试就是这个(三个次级):
select art.id,
art.weight,
art.price,
(select sum(pos.qty) from pos inner join dok on pos.dok_id = dok.id where year(dok.date) = 2013 and pos.art_id = art.id),
(select sum(pos.qty) from pos inner join dok on pos.dok_id = dok.id where year(dok.date) = 2014 and pos.art_id = art.id),
(select sum(pos.qty) from pos inner join dok on pos.dok_id = dok.id where year(dok.date) = 2015 and pos.art_id = art.id)
from art;
效率非常低。
所以我写了一个查询,给我以下结果集(不包括每篇文章,因为并非所有文章都已售出):
art.id,year,qty
使用它作为左表加入它的表:
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
答案 0 :(得分:0)
您可以使用单个子查询,使用SUM中的IF仅将该字段中的值与特定年份的行相加。像这样(未经测试): -
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