2013-01-23 42 views
1

我有三个表,products,variantsdataMySQL查询:当使用ifnull连接表时响应慢

每个产品都有自己的productcode。产品可以有任何数量的变体,包括无。变体有自己的代码variantcode。产品列有productid列,每个变体都有相关的productid列。

我想要一个所有代码的列表,但如果产品没有变体,我只关心productcode。否则,我想要variantcode。我写了这个查询来得到这个列表:

SELECT IFNULL(variants.variantcode, products.productcode) AS code 
FROM products 
LEFT OUTER JOIN variants ON (products.productid = variants.productid) 
ORDER BY code 

这个查询按我的预期工作。

data表包含每个代码的额外数据。我想将这些数据加入到这个列表中。我想这个查询:

SELECT IFNULL(variants.variantcode, products.productcode) AS code 
FROM products 
LEFT OUTER JOIN variants ON (products.productid = variants.productid) 
LEFT OUTER JOIN data ON (data.partno = code) 
ORDER BY code 

但我“在‘关于条款’未知列‘代码’”得到一个错误。我以为这已经是与code是一个生成的值,所以后来我尝试此查询:

SELECT IFNULL(variants.variantcode, products.productcode) AS code 
FROM products 
LEFT OUTER JOIN variants ON (products.productid = variants.productid) 
LEFT OUTER JOIN data ON (data.partno = IFNULL(variants.variantcode, products.productcode)) 
ORDER BY code 

这个查询工作,但花了很长时间(〜20秒VS < 1秒第一个查询) 。 ON子句中的IFNULL是否是问题?我如何加快速度?

+0

你需要使用一个派生查询此。 – Kermit

回答

1

试试这个:

select product_variants.code from 

(SELECT IFNULL(variants.variantcode, products.productcode) AS code 
FROM products 
LEFT OUTER JOIN variants ON (products.productid = variants.productid) 
ORDER BY code) 

as product_variants 

LEFT OUTER JOIN data ON (data.partno = product_variants.code) 
+0

这个伎俩!张贴在此之后我看着衍生查询所推荐的@njk,写下这样的查询: 'SELECT product_variants.code FROM (SELECT IFNULL(variants.variantcode,products.productcode)AS代码 从产品 LEFT OUTER JOIN变异体(products.productid = variants.productid)) AS product_variants LEFT OUTER JOIN ON(data.partno = product_variants.code) ORDER BY数据product_variants.code' 其中的工作,但仍了20秒。为什么移动ORDER BY加快速度? – pjgat09

+1

您可以通过在查询前添加'EXPLAIN'关键字来检查执行计划如何受到影响,例如'EXPLAIN select product_variants.code ...'它会显示是否使用了索引以及返回的估计行数。 –

+0

感谢@Adrian的建议。我花了一点时间看看EXPLAIN,并没有在'data'上使用任何索引。我尝试修改索引,但没有使用。使用与“productcode”和“variantcode”不同的排序规则来表示'partno'字段。这是因为我在做桌时出现了错误。我改变了排序来匹配,现在我的查询运行得很快。 – pjgat09

0

有一件事你可以尝试是加入到你的data表两次,这样的事情:

SELECT IFNULL(variants.variantcode, products.productcode) AS code 
    , IFNULL(D1.something, D2.something) AS something 
FROM products 
LEFT OUTER JOIN variants 
ON (products.productid = variants.productid) 
LEFT OUTER JOIN data as D1 
ON (D1.partno = variants.variantcode) 
LEFT OUTER JOIN data as D2 
ON (D2.partno = products.productcode) 
ORDER BY code 
+0

这似乎会工作,但不会需要'数据'中的每一列IFNULL? – pjgat09

+0

是的,从你的问题中不清楚你需要'data'中的所有列。使用上面的派生表可能是最好的;我只是表现出不同的方式。 – BellevueBob

+0

啊,好的。我的头脑中有一个类似这样的想法,所以很高兴看到它写出来。谢谢! – pjgat09