1

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.

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. The optionsets table connects each ProductItemID to the dropdown options it is associated with. 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.

Here is an example query that gets me the total price for an individual 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 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. That way, I would no longer have to loop through a PHP array to do it. 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. So my questions are, how do I reformulate the query to only need 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? 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. 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. Cue three weeks of headache and counting.

5
  • If you want help, could you reformat the query and provide an alias for every column? It is not possible to follow the query, because we don't know the table structures. Commented May 18, 2012 at 1:25
  • use js fiddle to create structure and then we will be able to sort out your problem Commented May 18, 2012 at 5:18
  • @raheelshan I think SQLFiddle might be more appropriate :) Commented May 18, 2012 at 8:02
  • yeah sorry in hurry made a mistake Commented May 18, 2012 at 11:33
  • Sorry I never heard of SQL Fiddle before. Let me know if I didn't do it correctly. Commented May 18, 2012 at 17:04

1 Answer 1

1

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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.