有效地返回3个表中的最低分组值

时间:2014-07-14 22:13:27

标签: mysql sql performance

我目前正在尝试实现搜索引擎功能,尝试有效地从3个表中返回信息。用法是数字搜索,无法使用自由文本,因此我不会尝试针对此方案进行优化。

使用的表格如下:

Companies hasMany Products
Products hasMany Prices

问题如下:

我想为符合任何指定标准的每家公司退回最便宜的单品(这可能是产品或价格的标准)

我的解决方案如下:

SELECT * FROM (
SELECT Company.id, Company.name AS CompanyName, Product.name, Product.quantity, Price.price
FROM Product
LEFT JOIN Price ON Product.id=Price.product_id
LEFT JOIN Company ON Product.company_id=Company.id
/* EXAMPLE CONDITIONS */
WHERE Price.price > 10 AND Product.quantity > 4
ORDER BY Price.price
) AS tmp_table
GROUP BY tmp_table.id
ORDER BY tmp_table.price;

问题:这种子查询方法是否是实现此解决方案的最有效方法?

执行时间从1毫秒到140毫秒不等,共有3家公司,每家公司有3个产品,每个产品都有3个价格,所以如果要达到数百个,可能会变得混乱。

我在http://sqlfiddle.com/#!2/c194b7/1/0

创建了一个SQL小提琴

1 个答案:

答案 0 :(得分:1)

此查询依赖于MySQL的“功能”,具体记录 无法正常工作。也就是说,您假设外部group by中的额外列来自第一行,而documentation明确指出:

  

MySQL扩展了GROUP BY的使用,以便选择列表可以引用   未在GROUP BY子句中命名的非聚合列。这意味着   前面的查询在MySQL中是合法的。您可以使用此功能   通过避免不必要的列排序来获得更好的性能   分组。但是,这主要适用于每个中的所有值   GROUP BY中未命名的非聚合列对于每个列都是相同的   组。服务器可以自由选择每个组中的任何值,所以   除非它们相同,否则所选值不确定

我不推荐您使用的方法。

由于您使用的是group by,因此可以使用group_concat() / substring_index()方法执行此操作:

SELECT c.id, c.name AS CompanyName, Product.name,
       substring_index(group_concat(p.name order by pr.price, p.product_id), ',', 1) as price,
       substring_index(group_concat(p.quantity order by pr.price, p.product_id), ',', 1) as price,
       MIN(pr.price) as price
FROM Product p LEFT JOIN
     Price pr
     ON p.id = pr.product_id LEFT JOIN
     Company c
     ON p.company_id = c.id
WHERE pr.price > 10 AND p.quantity > 4
GROUP BY c.id, c.name
ORDER BY pr.price;