0

我正在尝试在我的网站上获取一组商家的订单金额。我必须检查两种项目类型,这使得查询非常慢。这是我现在使用的(为便于阅读而转录)查询

SELECT User.ID, COUNT(Order.ID) FROM User
  INNER JOIN UserGroup ON UserGroup.userID = User.ID AND UserGroup.groupID = 4
  LEFT JOIN Meal ON Meal.userID = User.ID
  LEFT JOIN Produce ON Produce.userID = User.ID
  LEFT JOIN Order ON (type = 'Meal' AND typeID = Meal.ID) OR (type = 'Produce' AND typeID = Produce.ID)
WHERE Order.rating > 50 AND Order.status = 'DELIVERED'
ORDER BY User.ID ORDER BY COUNT(Order.ID) DESC

当然,所有链接和状态列都是索引。当我运行EXPLAIN查询时,我可以看到它以 形式加入Order表格type ALL,我很确定这是问题所在,我只是不知道如何让它也加入ref。目前执行需要 2.74 秒。

(不要检查此查询中的拼写错误,为了便于阅读,我更改了表和字段名称,并且可能遗漏了一些内容,但是有关我的问题的所有信息都在其中。)

的输出EXPLAIN

+----+-------------+-----------+--------+-------------------------+---------+---------+------------------+------+---------------------------------+
| id | select_type | table     | type   | possible_keys           | key     | key_len | ref              | rows | Extra                           |
+----+-------------+-----------+--------+-------------------------+---------+---------+------------------+------+---------------------------------+
|  1 | SIMPLE      | UserGroup | ref    | userID,groupID          | groupID | 4       | const            |   74 | Using temporary; Using filesort |
|  1 | SIMPLE      | User      | eq_ref | PRIMARY,isDeleted       | PRIMARY | 4       | UserGroup.userID |    1 | Using where                     |
|  1 | SIMPLE      | Meal      | ref    | userID,isDeleted,status | userID  | 4       | UserGroup.userID |   18 |                                 |
|  1 | SIMPLE      | Produce   | ref    | userID,status,isDeleted | userID  | 4       | User.ID          |   13 |                                 |
|  1 | SIMPLE      | Order     | ALL    | status,isDeleted,type   | NULL    | NULL    | NULL             | 1960 |                                 |
+----+-------------+-----------+--------+-------------------------+---------+---------+------------------+------+---------------------------------+
4

1 回答 1

0

我已经解决了这个问题。我可以走两条路:

使用UNION上面评论中建议的 a (执行时间:~ 10.5ms)

SELECT User.ID, SUM(orderCount) AS totalOrders FROM (
  (
    SELECT User.ID, COUNT(Order.ID) AS orderCount
    FROM User
    INNER JOIN UserGroup ON User.ID = UserGroup.userID AND UserGroup.groupID = 4
    LEFT JOIN Meal ON User.ID = Meal.userID
    LEFT JOIN Order ON Order.type = 'Meal' AND Order.typeID = Meal.ID
    GROUP BY User.ID
  )
  UNION ALL
  (
    SELECT User.ID, COUNT(Order.ID) AS orderCount
    FROM User
    INNER JOIN UserGroup ON User.ID = UserGroup.userID AND UserGroup.groupID = 4
    LEFT JOIN Produce ON User.ID = Produce.userID
    LEFT JOIN Order ON Order.type = 'Produce' AND Order.typeID = Produce.ID
    GROUP BY User.ID
  )
) AS uni
GROUP BY User.ID
ORDER BY totalOrders DESC

或者我可以将Order表设为主表并执行GROUP BY COALESCE()(执行时间:~76 ms)

SELECT COALESCE(Meal.userID,Produce.userID) AS cook, COUNT(Order.ID) AS totalOrders 
FROM Order
LEFT JOIN Meal ON Order.type = 'Meal' AND Order.typeID = Meal.ID
LEFT JOIN Produce ON Order.type = 'Produce' AND Order.typeID = Produce.ID
INNER JOIN UserGroup ON UserGroup.groupID = 4 AND (Meal.userID = UserGroup.userID OR Produce.userID = UserGroup.userID)
GROUP BY cook
HAVING cook IS NOT NULL
ORDER BY TotalOrders DESC

为了可读性,我决定使用后者。如果有人知道如何解决我在原始问题中的查询,请告诉我。我把它写成一个更大的脚本的一部分,在那里我可以快速加入查询修饰符。如果我必须对查询进行如此多的更改,这些将不再起作用。

于 2013-07-29T23:08:50.140 回答