2012-05-18 2 views
1

Чтобы сделать длинный рассказ короче, у меня есть несколько сложных запросов (см. Пример ниже), и вам нужно сохранять их результаты в таблицу, а не запускать их каждый раз. У меня около 6 месяцев опыта работы с MYSQL, поэтому я знаю достаточно, чтобы попасть в неприятности.оптимизация запроса mysql с вложенными подзапросами

Справочная информация: каждый продукт имеет несколько правил, определяющих цены, доставку и т. Д. Таблица kitruleoptions соединяет каждое правило с выпадающими вариантами, к которым оно будет применяться - так, если клиент выбирает «Добавить необязательный X», правила, относящиеся к Xs применяется. Таблица optionsets соединяет каждый ProductItemID с параметрами выпадающего списка, с которыми он связан. Таким образом, правило должно применяться для определенного элемента продукта только в том случае, если в раскрывающемся списке этого правила отображаются все раскрывающиеся параметры элемента продукта. Другими словами, это не значит, что правило обязательно применяется каждый раз, когда выбран X, но, скорее, он может применяться каждый раз, когда X выбран в раскрывающемся списке A, а либо Y, либо Z выбраны в выпадающем списке B, но не в том случае, если в выпадающем списке выбрано значение W B.

Вот пример запроса, который дает мне общую цену для отдельного ProductItemID.

SELECT ProductItemID, SUM(RulePrice * ItemQuantity) AS Price FROM 
(SELECT RuleGroups, ProductItemGroups, RulePrice, ItemQuantity, productitems.ProductItemID 
FROM kitrules 
LEFT JOIN productitems ON productitems.ProductID = kitrules.ProductID 
LEFT JOIN (SELECT RuleID, GROUP_CONCAT(OptionGroupID ORDER BY OptionGroupID) AS RuleGroups 
    FROM kitruleoptions 
    WHERE OptionGroupID IN (SELECT OptionGroupID FROM optionsets WHERE ProductItemID = %s) 
    GROUP BY RuleID) AS k ON k.RuleID = kitrules.RuleID 
LEFT JOIN (SELECT ProductItemID, GROUP_CONCAT(OptionGroupID ORDER BY OptionGroupID) AS ProductItemGroups 
    FROM optionsets 
    GROUP BY ProductItemID) AS o ON o.ProductItemID = productitems.ProductItemID 
WHERE productitems.ProductItemID = %s AND RuleGroups = ProductItemGroups) AS x 
GROUP BY x.ProductItemID 

В настоящее время этот выбор (или, скорее, более сложный, который выбирает больше, чем просто цена) идет внутри INSERT INTO заявление примерно так:

INSERT INTO pricelists (ProductItemID, Price) 
SELECT [the query above] 
WHERE ProductItemID = %s 

Я пытаюсь сформулировать вместо этого примерно так:

INSERT INTO pricelists (ProductItemID, Price) 
SELECT [a new query that only requires ProductID] 
WHERE ProductItemID IN (SELECT ProductItemID FROM productitems WHERE ProductID = %s) 

... и нужно только ввести ProductID, чтобы сразу обновить весь продукт. Таким образом, мне больше не придется перебирать массив PHP для этого. ProductID найден как в таблице kitrules, так и в таблице productitems, поэтому я чувствую, что должен быть способ, но я не могу найти его. Итак, мои вопросы: как мне переформулировать запрос только для ProductID? Возможно ли это? Есть ли способ напрямую сравнить набор наборов параметров и набор наборов без объекта GROUP_CONCAT? Кроме того, как бы я установил это с помощью триггера и на что он должен срабатывать? Раньше я никогда не делал триггеры.

EDIT: Вот мой SQL Fiddle, который имеет простой пример того, как должны заканчиваться таблицы. Идея заключается в том, что я начал с установки, в которой каждый продукт просто имел один или несколько элементов, но затем из-за позднего изменения требований (yay) мне пришлось добавить способность создавать элементы, которые представляют собой наборы или комбинации несколько разных предметов, и все же наборы - это предметы сами. Требование состоит в том, что ItemCost комплекта представляет собой сумму его предметов ItemCosts, и стоимость комплекта - это сумма его содержащихся правил «RulePrices times ItemQuantity», а его доставка определяется комбинированной отправкой информации о доставке содержащихся в ней предметов, но в остальном, комплект - это еще один предмет. Попробуйте три недели головной боли и подсчета.

+0

Если вы хотите помочь, вы можете переформатировать запрос и предоставить псевдоним для каждого столбца? Невозможно выполнить запрос, потому что мы не знаем структуры таблицы. –

+0

использовать js скрипку для создания структуры, и тогда мы сможем разобраться в вашей проблеме. –

+0

@raheelshan. Я думаю, что [SQLFiddle] (http://sqlfiddle.com/) может быть более уместным :) – GarethD

ответ

1

Я понял это в конце концов:

SELECT ProductItemID, SUM(RulePrice * ItemQuantity) AS TotalPrice FROM 
(SELECT p.ProductItemID, k.RuleID, p_count, COUNT(k.RuleID) AS k_count, 
RulePrice, ItemQuantity 
FROM productitems 
INNER JOIN optionsets o ON productitems.ProductItemID = o.ProductItemID 
INNER JOIN (SELECT ProductItemID, COUNT(OptionGroupID) AS p_count 
     FROM optionsets 
     GROUP BY ProductItemID) AS p ON p.ProductItemID = o.ProductItemID 
LEFT JOIN kitruleoptions k ON k.OptionGroupID = o.OptionGroupID 
LEFT JOIN kitrules ON k.RuleID = kitrules.RuleID 
WHERE productitems.ProductID = %s 
GROUP BY o.ProductItemID, k.RuleID 
HAVING k_count = p_count) AS x 
GROUP BY x.ProductItemID 
Смежные вопросы