Преобразование подзапросов в операторы JOIN для MySQL? - PullRequest
0 голосов
/ 18 марта 2020

Вот мой текущий запрос:

 SELECT prod.id,
       prod.title,
       prod.price,
       prod.status,
       (SELECT COUNT(*)
        FROM   payments
        WHERE  product = prod.id
               AND ( vendor = '1'
                     AND credited = 'Vendor' )
               AND ( status = 'Completed'
                      OR status = 'Pending'
                      OR status = 'Canceled_Reversal' )) AS sales,
       (SELECT SUM(price)
        FROM   payments
        WHERE  product = prod.id
               AND ( vendor = '1'
                     AND credited = 'Vendor' )
               AND ( status = 'Completed'
                      OR status = 'Pending'
                      OR status = 'Canceled_Reversal' )) AS revenue
FROM   products prod
WHERE  member = '1'
       AND status != 'Deleted' 
       AND status != 'Blocked'  

Прямо сейчас я использую 2 подзапроса внутри основного запроса.

Есть ли способ использовать вместо операторов JOIN или упростить запрос до ускорить?

Или ничто не сделает это намного быстрее?

Ответы [ 2 ]

0 голосов
/ 18 марта 2020

Используйте объединение с агрегацией:

SELECT
    prod.id,
    prod.title,
    prod.price,
    prod.status,
    COALESCE(t.sales, 0) AS sales,
    COALESCE(t.revenue, 0) AS revenue
FROM products prod
LEFT JOIN
(
    SELECT
        product,
        COUNT(*) AS sales,
        SUM(price) AS revenue
    FROM payments p
    WHERE vendor = '1' AND credited = 'Vendor' AND
          status IN ('Completed', 'Pending', 'Canceled_Reversal')
    GROUP BY product
) t
    ON t.product = prod.id;

Обратите внимание, что здесь используется объединение left , чтобы учесть вероятность того, что какой-либо продукт в таблице products может даже не совпадать есть любые подходящие данные в таблице payments. В этом случае мы также используем COALESCE, чтобы сообщить нулевые значения для продаж и выручки.

Подзапрос с псевдонимом t выше, вероятно, может быть оптимизирован с использованием следующего индекса:

payments (product, vendor, credit, status, price)
0 голосов
/ 18 марта 2020

Я бы написал это немного проще:

SELECT p.id, p.title, p.price, p.status,
       (SELECT COUNT(*)
        FROM payments pa
        WHERE pa.product = p.id AND
              pa.vendor = p.member AND
              pa.credited = 'Vendor' AND
              pa.status IN ('Completed','Pending', 'Canceled_Reversal')
      ) AS sales,
       (SELECT SUM(pa.price)
        FROM payments pa
        WHERE pa.product = p.id AND
              pa.vendor = p.member AND
              pa.credited = 'Vendor' AND
              pa.status IN ('Completed','Pending','Canceled_Reversal')
      ) AS revenue
FROM products p
WHERE p.member = 1 AND
      p.status NOT IN ('Deleted', 'Blocked');

Это в основном ваш запрос с более простыми псевдонимами и логами c.

С индексом на payments(product, vendor, credit, status, price) это вероятно, быстрее, чем другие методы.

Альтернатива:

SELECT p.id, p.title, p.price, p.status,
       COUNT(pa.product) as sales
       SUM(pa.price) as revenue
FROM products p LEFT JOIN
     payments pa
     ON pa.product = p.id AND
        pa.vendor = p.member AND
        pa.credited = 'Vendor' AND
        pa.status IN ('Completed', 'Pending', 'Canceled_Reversal')
WHERE p.member = 1 AND
      p.status NOT IN ('Deleted', 'Blocked')
GROUP BY p.id, p.title, p.price, p.status;

Однако подзапросы, вероятно, быстрее.

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