Есть ли способ для правильного подзапроса условия замены с JOINs и оптимизации этих запросов типа? - PullRequest
0 голосов
/ 10 июня 2019

Я ищу какой-нибудь хороший способ оптимизировать эти запросы путем удаления подзапросов и реорганизации для возможных индексов, но я застрял (

1-й

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 дней "(или вообще не делали никаких заказов)

выглядит хорошо, работает хорошо, но вызывает у меня сомнения ...

2-nd

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 покупателей, которые сделали наибольшее количество заказов в магазине»

Есть идеи получше? (

3-й

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 лучших имен клиентов, которые сделали заказы на наибольшую сумму»

слишком медленное решение (((и понятия не имеем об индексах (

4-й * 1024)*

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

легенда: «названия всех продуктов, на которые не было доставлено заказов»

снова - подзапрос ...

спасибо за помощь и любые идеи)

Ответы [ 2 ]

0 голосов
/ 10 июня 2019

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;
0 голосов
/ 10 июня 2019

Я полагаю, что вызов функции не включен, а также присоединение к другой таблице, и пусть MySql Compare может быть немного дорогостоящим.Для этого я бы попросил программу соединить значения и исключить их из программы.Для 2-го и 3-го , я полагаю, вы делаете наилучшую возможность.Выполнение подзапросов стоит дороже, как для first и четвертого , для тех, как я упоминал ранее, я мог бы просто сделать один запрос, объединяя нужные мне данные и работать с ними надПрограмма, которую я пишу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...