2012-05-18 7 views
1

간단히 말해서 복잡한 쿼리 (아래 예 참조)가 있으므로 매번 실행하지 않고 테이블에 결과를 저장해야합니다. 나는 MYSQL에 대해 6 개월의 경험을 가지고 있으므로 문제를 일으키기에 충분하다는 것을 알고 있습니다.중첩 된 하위 쿼리를 사용하여 mysql 쿼리를 최적화하는 방법

배경 : 가격, 배송 등을 결정하는 여러 가지 규칙이 각 제품에 있습니다. kitruleoptions 테이블은 각 규칙을 적용 할 드롭 다운 옵션에 연결합니다. 따라서 고객이 "선택 X 추가"를 선택하면 Xs가 적용됩니다. 옵션 세트 테이블은 각 ProductItemID를 연관된 드롭 다운 옵션에 연결합니다. 따라서 모든 제품 항목의 드롭 다운 옵션이 해당 규칙의 드롭 다운 옵션 세트에있는 경우에만 규칙이 특정 제품 항목에 적용되어야합니다. 즉, X가 선택 될 때마다 규칙이 반드시 적용되는 것이 아니라 드롭 다운 A에서 X가 선택되고 드롭 다운 B에서 Y 또는 Z가 선택 될 때마다 적용될 수 있지만 드롭 다운에서는 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을 사용하지 않고 옵션 세트와 kitruleoptions 세트를 직접 비교할 수있는 방법이 있습니까? 또한, 어떻게 이것을 트리거로 설정하고 트리거해야합니까? 전에는 트리거를 한 번도하지 않았습니다.

편집 : 여기 내 SQL Fiddle에는 테이블이 어떻게 끝날지에 대한 간단한 예가 있습니다. 아이디어는 각 제품에 하나 이상의 항목이 있었지만 요구 사항의 늦은 변경 (예)으로 인해 키트로 된 항목을 생성 할 수있는 기능을 추가해야한다는 설정으로 시작했습니다. 여러 개의 다른 항목이 있지만 키트는 항목 자체입니다. 요구 사항은 키트의 ItemCost가 포함 된 항목의 ItemCosts의 합계이고 키트의 가격이 포함 된 규칙의 RulePrices 시간 ItemQuantity의 합계이고 해당 운송은 포함 된 품목의 운송 정보의 결합 된 운송에 의해 결정되며, 그렇지 않으면 키트는 단지 또 다른 항목입니다. 3 주간의 두통과 세어 카운트.

+0

도움을 원하는 경우에, 당신은 쿼리를 다시 포맷하고 모든 열 별칭을 제공 할 수있다? 우리는 테이블 구조를 모르기 때문에 쿼리를 따르는 것은 불가능합니다. –

+0

구조를 만들기 위해 js fiddle을 사용하면 문제를 해결할 수 있습니다. –

+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 
관련 문제