Минимизация избыточности запроса MySQL

#mysql

#mysql

Вопрос:

У меня возникли небольшие проблемы при попытке уменьшить избыточность запроса в MySQL. В настоящее время у меня это работает, но мне кажется, что у меня слишком много накладных расходов, потому что он использует избыточный подзапрос. Что я пытаюсь сделать, так это использовать базу данных проката DVD, чтобы найти, в каком магазине было арендовано больше DVD-дисков за каждый месяц в 2005 году.

Вот рабочий запрос

 SELECT b.month, c.store_id, b.maxRentals
FROM
    (SELECT a.month, MAX(a.rentalCount) as maxRentals
    FROM
        (SELECT MONTH(rental.rental_date) as month, inventory.store_id, count(1) as rentalCount
        FROM rental

        INNER JOIN inventory
        ON rental.inventory_id = inventory.inventory_id

        WHERE YEAR(rental.rental_date) = 2005

        GROUP BY MONTH(rental.rental_date), inventory.store_id
        ) a
    GROUP BY a.month
    ) b

    INNER JOIN

    (SELECT MONTH(rental.rental_date) as month, inventory.store_id, count(1) as rentalCount
    FROM rental

    INNER JOIN inventory
    ON rental.inventory_id = inventory.inventory_id

    WHERE YEAR(rental.rental_date) = 2005

    GROUP BY MONTH(rental.rental_date), inventory.store_id
    ) c
ON b.maxRentals = c.rentalCount

GROUP BY b.month;
  

Обратите внимание, что подзапрос с псевдонимом «c» является точно таким же подзапросом с псевдонимом «a». Я не уверен, есть ли способ избавиться от этого, поскольку я не могу выполнить внутреннее соединение с псевдонимом. Я просто застрял с гигантским запросом, или есть что-то еще, что я могу сделать?

Комментарии:

1. MySQL 8 (в настоящее время в бета-версии) будет реализовывать общие табличные выражения, так что вы сможете делать это в будущем с меньшей избыточностью. Или вы могли бы переключиться на PostgreSQL или любую другую базу данных SQL.

2. Как насчет CREATE TEMPORARY TABLE IF NOT EXISTS invent AS (SELECT [subquery SQL here]) того, чтобы затем присоединиться к invent (и отбросить в конце)?

3. Теперь, глядя на ваш код, я думаю, что его можно переписать с помощью CASE … позвольте мне попробовать…

Ответ №1:

Я на 90% уверен, что этот запрос достигнет ваших намерений:

 SELECT MONTH(r.rental_date), i.store_id, COUNT(*)
FROM rental r
LEFT JOIN inventory i ON r.inventory_id = i.inventory_id
WHERE YEAR(r.rental_date) = 2005
GROUP BY MONTH(r.rental_date), i.store_id
  

Дайте мне знать, как это происходит!

Редактировать: чтобы ответить на вопрос, в каком магазине было арендовано больше DVD-дисков за каждый месяц в 2005 году:

 SELECT x.rental_month, x.store_id, MAX(x.rental_count) FROM (
SELECT MONTH(r.rental_date) AS rental_month, i.store_id AS store_id, COUNT(*) AS rental_count
FROM rental r LEFT JOIN inventory i ON r.inventory_id = i.inventory_id
WHERE YEAR(r.rental_date) = 2005
GROUP BY MONTH(r.rental_date), i.store_id) x
GROUP BY x.rental_month, x.store_id
  

Я был откровенен, используя псевдонимы везде, вы, вероятно, могли бы опустить некоторые. Надеюсь, это поможет…

Редактировать: грязный взлом:

 SELECT x.rental_month, x.store_id, MAX(x.rental_count) FROM (
SELECT MONTH(r.rental_date) AS rental_month, i.store_id AS store_id, COUNT(*) AS rental_count
FROM rental r LEFT JOIN inventory i ON r.inventory_id = i.inventory_id
WHERE YEAR(r.rental_date) = 2005
GROUP BY MONTH(r.rental_date), i.store_id
ORDER BY MONTH(r.rental_date) ASC, COUNT(*) DESC) x
GROUP BY x.rental_month
  

Ссылка:
http://kristiannielsen.livejournal.com/6745.html

Но тогда это удовлетворяет вас, поскольку у вас уже есть рабочий запрос…

Комментарии:

1. Этот запрос такой же, как мои подзапросы a amp; c. Это было бы правильно, если бы он возвращал только месяц, хранилище и количество для хранилища с наибольшим количеством арендуемых в месяц, чего я и пытаюсь достичь выше. Технически, вы действительно можете легко определить, какой магазин арендовал больше в месяц из этой таблицы, но это не совсем то, для чего мне нужен запрос.

2. Ах, я только что опубликовал правку, но позвольте мне прочитать ваш комментарий, чтобы узнать, обращается ли он к ней…

3. Я полагаю, что редактирование касается комментария и намерения?

4. используя x.store_id в предложении group by, этот запрос возвращает точно такой же результат, как и первый. Однако без этого вернутся месяцы и максимальное количество арендованных, но неправильное хранилище.

5. Спасибо, это очень интересная проблема, ссылка хорошо справляется с обсуждением решений и их сроков.