有没有办法用JOIN正确替换条件子查询并优化那些类型查询?

时间:2019-06-10 13:17:36

标签: mysql join optimization subquery

我正在寻找通过删除子查询并重新组织可能的索引来优化这些查询的任何好方法,但是我坚持(

1-st

SELECT 
    `clients`.`name`,`clients`.`id`
FROM 
    `clients`
WHERE 
    `id` NOT IN (
        SELECT `orders`.`customer_id` FROM `orders` 
        WHERE `orders`.`order_date` BETWEEN NOW() - INTERVAL 7 DAY AND NOW()
    )
;

传奇:“过去7天未下任何订单的客户姓名” (或根本没有下任何订单)

看起来不错,运作良好,但是让我怀疑...

2nd

SELECT 
    `clients`.`name`,`clients`.`id`,COUNT(*)
FROM 
    `clients`
INNER JOIN  `orders` ON
    `clients`.`id` = `orders`.`customer_id`   
        GROUP BY `orders`.`customer_id` ORDER BY COUNT(*) DESC,`id` LIMIT 0,5;

传奇:“在商店中获得最多订单的前5名客户”

有更好的主意吗? (

3rd

SELECT 
     `clients`.`name`
     ,SUM(`merchandise`.`price`) as `TotalPrice`
     ,count(*)
FROM 
    `orders`
INNER JOIN  `clients` ON
    `orders`.`customer_id` = `clients`.`id`
INNER JOIN  `merchandise` ON
    `orders`.`item_id` = `merchandise`.`id`

GROUP BY 
    `orders`.`customer_id`
ORDER BY 
    `TotalPrice` DESC
LIMIT 
    0,10
;

传奇:“订单金额最高的前10名客户”

解决方案太慢((((而且不知道索引(

4th

SELECT 
    `merchandise`.`name`
FROM
    `merchandise`
WHERE `id` NOT IN 
(
    SELECT
        `orders`.`item_id`
    FROM 
        `orders`
    WHERE 
        `orders`.`status` = 'complete'
)
;

图例:“未交付订单的所有产品的名称”

再次

-子查询...

感谢您的帮助和任何想法)

2 个答案:

答案 0 :(得分:0)

FWIW,称我为老式,但我会以这种方式编写第一个查询,并在(customer_id,order_date)上加上复合索引

SELECT c.name
     , c.id
  FROM clients c
  LEFT
  JOIN orders o 
    ON o.customer_id = c.id
   AND o.order_date BETWEEN NOW() - INTERVAL 7 DAY AND NOW()
 WHERE o.id IS NULL;

第二个查询很好,但是我还是用上面提到的索引这样写的……

SELECT c.name
     , c.id
     , COUNT(*) total
  FROM clients c
  JOIN orders o
    ON o.customer_id = c.id 
 GROUP  
    BY c.name
     , c.id
 ORDER 
    BY total DESC
     , id 
 LIMIT 0,5;

再次,第三个似乎很好。我觉得这更容易阅读:

SELECT c.name
     , SUM(m.price) TotalPrice
     , count(*) quantity
  FROM clients c
  JOIN orders o
    ON o.customer_id = c.id
  JOIN merchandise m
    ON m.id = o.item_id 
 GROUP 
    BY c.name
     , c.id
 ORDER 
    BY TotalPrice DESC
 LIMIT 0,10;

与第一个问题相同(但在(item_id,status)上有一个复合索引,我会这样写第四个问题-尽管NOT EXISTS可能会更快:

SELECT m.name
  FROM merchandise m
  LEFT
  JOIN orders o
    ON o.item_id = m.id
   AND o.status = 'complete'
 WHERE o.item_id IS NULL;

答案 1 :(得分:-1)

我相信not in function调用以及加入另一个表并让MySql Compare可能有点贵。为此,我将让程序进行连接值的查询,并在程序中排除。对于第二名第三名,我相信您正在尽最大努力。子查询的确要花更多的钱,对于第一第四,对于那些,正如我之前提到的,我可能只做一个查询就可以连接我需要的数据并使用它们在我正在编写的程序上。