此查询是否看起来优化了?

时间:2008-10-02 09:39:33

标签: mysql sql optimization

我正在编写一个应用程序的查询,该应用程序需要列出所有产品的购买次数。

我提出了这个并且它有效,但我不太确定它是如何优化的。由于我大量使用ORM,我的SQL真的很生疏,但在这种情况下,查询是一个更优雅的解决方案。

你能用查询发现任何错误(方法明智)吗?


SELECT  products.id, 
        products.long_name AS name, 
        count(oi.order_id) AS sold
FROM    products
LEFT OUTER JOIN 
      ( SELECT * FROM orderitems
        INNER JOIN orders ON orderitems.order_id = orders.id 
        AND orders.paid = 1 ) AS oi 
      ON oi.product_id = products.id
GROUP BY products.id

架构(带有相关字段)如下所示:

*orders*      id, paid
*orderitems*  order_id, product_id
*products*    id

更新

这是针对MySQL的

6 个答案:

答案 0 :(得分:3)

我不确定“(SELECT *”......业务。

执行(总是一个好的开始),我认为等同于发布的内容。

SELECT  products.id, 
    products.long_name AS name, 
    count(oi.order_id) AS sold
FROM    products
LEFT OUTER JOIN
    orderitems AS oi
        INNER JOIN 
            orders 
            ON oi.order_id = orders.id AND orders.paid = 1
    ON oi.product_id = products.id
GROUP BY products.id

答案 1 :(得分:2)

这是我们这些筑巢的人的解决方案。 (当我开始嵌套连接时,我感到很困惑)

SELECT  products.id, 
    products.long_name AS name, 
    count(oi.order_id) AS sold
FROM orders 
    INNER JOIN orderitems  AS oi ON oi.order_id = orders.id AND orders.paid = 1
    RIGHT JOIN products ON oi.product_id = products.id
GROUP BY products.id

但是,我测试了你的解决方案,迈克和我的MS SQL Server和查询计划是相同的。我不能代表MySql,但如果MS SQL Server可以通过,你可能会发现所有三种解决方案的性能相当。如果是这种情况,我想你会选择哪种解决方案最清楚。

答案 2 :(得分:1)

它能给你正确答案吗?

除了修改它以去除内部查询中的SELECT之外,我没有看到它有什么问题。

答案 3 :(得分:0)

你有“LEFT OUTER JOIN”,这可能是一个性能问题,具体取决于你的数据库。 上次我记得它在MySQL上造成了地狱,它在SQLite中不存在。我认为Oracle可以处理它,我猜数据库和MSSQL也是如此。

编辑:如果我没记错的话LEVE OUTER JOIN在MySQL上会慢几个数量级,但如果我在这里过时,请纠正我:)

答案 4 :(得分:0)

未经测试的代码,但请尝试:

SELECT  products.id,
    MIN(products.long_name) AS name, 
    count(oi.order_id) AS sold
FROM    (products
LEFT OUTER JOIN orderitemss AS oi ON oi.product_id = products.id)
INNER JOIN orders AS o ON oi.order_id = o.id 
WHERE orders.paid = 1
GROUP BY products.id

我不知道LEFT OUTER JOIN是否需要括号,如果MySQL允许多个连接,则MIN(products.long_name)只提供描述,因为对于每个products.id,您只有一个描述

也许圆括号需要围绕INNER JOIN。

答案 5 :(得分:0)

这是一个子查询表单。

SELECT
  p.id,
  p.long_name AS name,
  (SELECT COUNT(*) FROM OrderItems oi WHERE oi.order_id in
    (SELECT o.id FROM Orders o WHERE o.Paid = 1 AND o.Product_id = p.id)
  ) as sold
FROM Products p

它应该大致相当于连接形式。如果没有,请告诉我。