简体   繁体   English

使用嵌套子查询优化mysql查询

[英]optimizing mysql query with nested subqueries

To make a long story short, I have some mildly complex queries (see example below) and need to save their results into a table rather than running them every time. 长话短说,我有一些比较复杂的查询(请参见下面的示例),需要将其结果保存到表中,而不是每次都运行它们。 I have about 6 months of experience with MYSQL, so I know just enough to get myself into trouble. 我有大约6个月的MYSQL经验,所以我知道足以使自己陷入麻烦。

Background: Each product has multiple rules that determine pricing, shipping, etc. The kitruleoptions table connects each rule to the dropdown options it will apply for -- so if a customer selects "Add optional X," the rules pertaining to Xs get applied. 背景:每种产品都有多个确定价格,运输等的规则。kitruleoptions表将每个规则连接到将要应用的下拉选项-因此,如果客户选择“添加可选X”,则将应用与Xs有关的规则。 The optionsets table connects each ProductItemID to the dropdown options it is associated with. optionsets表将每个ProductItemID连接到与其关联的下拉选项。 So, a rule should apply for a particular product item only if all of the product item's dropdown options are found in that rule's set of dropdown options. 因此,只有在该规则的下拉选项集中找到所有产品项的下拉选项时,该规则才应适用于该特定产品项。 In other words, it's not that the rule necessarily applies every time X is selected, but rather, it may apply every time X is selected in dropdown A and either Y or Z are selected in dropdown B, but not if W is selected in dropdown B. 换句话说,规则不一定是每次选择X时都适用,而是规则可能在每次在下拉列表A中选择X并且在下拉列表B中选择Y或Z时都适用,但是如果在下拉列表中选择W B.

Here is an example query that gets me the total price for an individual ProductItemID. 这是一个示例查询,可让我获取单个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

Currently, this select (or rather, a more complex one that selects more than just the price) goes inside an INSERT INTO statement somewhat like this: 当前,此选择(或者更复杂的选择而不只是价格)位于INSERT INTO语句中,如下所示:

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

I am trying to formulate it instead something like this: 我正试图制定它像这样:

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

... and only need to input ProductID in order to update the entire product at once. ...,只需输入ProductID即可立即更新整个产品。 That way, I would no longer have to loop through a PHP array to do it. 这样,我将不再需要遍历PHP数组来做到这一点。 ProductID is found in both the kitrules table and in the productitems table, so I feel like there should be a way, but I can't seem to find it. 在kitrules表和productitems表中都可以找到ProductID,所以我觉得应该有办法,但是我似乎找不到。 So my questions are, how do I reformulate the query to only need ProductID? 所以我的问题是,如何重新构造查询以仅需要ProductID? Is it even possible? 可能吗? Is there a way to directly compare the set of optionsets and the set of kitruleoptions without the GROUP_CONCAT thing? 有没有一种方法可以直接比较选项集的集合和kitruleoptions的集合,而无需使用GROUP_CONCAT? Also, how would I set this up with a trigger, and what should it trigger on? 另外,我将如何使用触发器来设置它,它应该在什么条件上触发? I've never done triggers before. 我以前从未做过触发器。

EDIT: Here is my SQL Fiddle which has a simple example of how the tables are supposed to end up. 编辑:这是我的SQL Fiddle ,其中有一个简单的示例,说明表应该如何结束。 The idea is that I started out with a setup where each product simply had one or more items, but then due to a late change in requirements (yay), I had to add in the ability to generate items that are kits, or combinations of multiple different items, and yet the kits are items themselves. 我的想法是,我从一个设置开始,每个产品仅包含一个或多个项目,但是由于需求的最新变化(是的),我不得不添加生成套件或套件组合项目的功能。多个不同的物品,而套件本身就是物品。 The requirement is that a kit's ItemCost is the sum of its contained items' ItemCosts, and a kit's Price is the sum of its contained rules' RulePrices times ItemQuantity, and its shipping is determined by the combined shipping of its contained items' shipping information, but otherwise, a kit is just another item. 要求是套件的ItemCost是其包含的物品的ItemCost的总和,套件的Price是其包含的规则的RulePrices乘以ItemQuantity的总和,其运送取决于其包含的物品的运送信息的合并运送,但是除此之外,套件只是另一回事。 Cue three weeks of headache and counting. 提示头痛三个星期并开始计数。

I figured it out eventually: 我最终弄清楚了:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM