1

同じオプション値が割り当てられている製品を抽出するクエリを作成しようとしています。影響を受けるテーブルは次のとおりです。

products
| id |

rel_product_options
| product | option | value |
"option" is an id from "options" table
"value" is an option value id from "values" table (an option can have multiple values. eg. option "color" can have "red", "blue" etc.)

すべての製品には、「rel_product_options」テーブルで複数のオプションと値の組み合わせがあります。同じ製品のバリエーションに同じオプションと値のペアを含めることはできないため、オプションの値を変更する前に、次の値が他の製品と競合しないかどうかを確認する必要があります。仮定しましょう

  • 商品A(色:赤、サイズ:10)
  • 商品B(色:青、サイズ:10)

ここで、「製品 B」の色を「赤」に変更しようとすると、データベースで「製品 A」のオプションが同一であることがわかり、変更をキャンセルできるはずです。質問が明確で、正直なところ、どこから始めればよいかさえわかりません。SQLは、何度使用しても謎のようなものです...以下のコードのようなものから始めましたが、私は私が数えることができるよりも多くのレベルでおそらく間違っていると思うので、どんな助けも大歓迎です。

# my thoughts
SELECT P1.*, PO1.*, PO2.* FROM products AS P1
# first select the product we want to extract all options from
# THIS ALREADY IS WRONG, because one of the options is ABOUT TO CHANGE, but this code assumes it has already done that
JOIN rel_product_options AS PO1 ON (PO1.product = P1.id AND PO1.product = 1)
# now join all other products that do not have identical option-value pairs
LEFT JOIN rel_product_options AS PO2 ON (PO1.product != PO2.product AND PO1.`option` = PO2.`option` AND PO1.value = PO2.value)
# and ... i'm lost ...
4

1 に答える 1

0

未テストですが、THIS_PRODUCT_ID の重複する商品を見つけるために次のようなことを試してください。の各行rel_product_optionsが一意であると想定していることに注意してください。

SELECT o2.product AS duplicateProduct 
FROM rel_product_options o
INNER JOIN rel_product_options o2 ON o.product <> o2.product 
    AND o.option = o2.option 
    AND o.value = o2.value
WHERE o.product = THIS_PRODUCT_ID
GROUP BY o2.product
HAVING COUNT(*) = (SELECT COUNT(*) 
                   FROM rel_product_options o3 
                   WHERE o3.product = THIS_PRODUCT_ID)

ON UPDATE編集:これを のトリガーに入れようとしているようですrel_product_options。これは少しハックですが、次のようなことを試すことができると思います。これはもちろん、OLD.product = NEW.productそれ以外の場合はすべての賭けがオフになっていることを前提としています。

SELECT o2.product AS duplicateProduct 
FROM
(
    SELECT product, 
        CASE WHEN option = OLD.option AND value = OLD.value THEN NEW.option ELSE option END AS option, 
        CASE WHEN option = OLD.option AND value = OLD.value THEN NEW.value ELSE value END AS value
    FROM rel_product_options
    WHERE product = NEW.product
) o
INNER JOIN rel_product_options o2 ON o.product <> o2.product 
    AND o.option = o2.option 
    AND o.value = o2.value
GROUP BY o2.product
HAVING COUNT(*) = (SELECT COUNT(*) 
                   FROM rel_product_options o3 
                   WHERE o3.product = NEW.product)

編集 2: これを PHP から実行し、パラメーターの値を変更する場合は、次のことを試すことができます。これは、 ( product, option) が一意であり、別の値を持つオプションが既に存在すると想定しています。つまりUPDATE、行を変更するために ではなく でクエリをフォローアップしますINSERT

SELECT o2.product AS duplicateProduct 
FROM
(
    SELECT product, 
        option, 
        CASE WHEN option = @option THEN @newValue ELSE value END AS value
    FROM rel_product_options
    WHERE product = @product
) o
INNER JOIN rel_product_options o2 ON o.product <> o2.product 
    AND o.option = o2.option 
    AND o.value = o2.value
GROUP BY o2.product
HAVING COUNT(*) = (SELECT COUNT(*) 
                   FROM rel_product_options o3 
                   WHERE o3.product = @product)

このクエリには 3 つのパラメーターがあります。

  • @product: 対象の製品 ID
  • @option: 変更するオプション
  • @newValue: オプションを変更する新しい値
于 2012-11-06T11:53:05.243 に答える