web-dev-qa-db-ja.com

複数の条件による複数の更新

次のIN句を使用して、nullに設定されている(不要な)ことに注意する必要があります。

UPDATE Tests SET
     TestScore =
              CASE
                  WHEN TestId = 10 THEN 1000
                  WHEN TestId = 11 THEN 1100
              END,
     TestScore2 =
              CASE
                  WHEN TestId = 10 THEN 2000
                  WHEN TestId = 11 THEN 2100
              END
     WHERE TestId IN (10, 11)

しかし、2つの条件、つまり(TestId、TestSubId)の組み合わせが必要になるとどうなりますか?つまり、以下のIN句である???は、(10,25)と(11,22)の組み合わせである必要があることを示すために何をしますか。

UPDATE Tests SET
    TestScore = CASE
        WHEN (TestId = 10 AND TestSubId = 25) THEN 1000
        WHEN (TestId = 11 AND TestSubId = 22) THEN 1100
    END,
    TestScore2 = CASE
        WHEN (TestId = 10 AND TestSubId = 25) THEN 2000
        WHEN (TestId = 11 AND TestSubId = 22) THEN 2100
    END
    WHERE TestId, TestSubId IN ?????
4
Rewind

MySQLでは、タプル比較を使用できます。

WHERE (TestId, TestSubId) IN ((10,25), (11,22))

ypercubeᵀᴹ がコメントで言及されているように、それはパフォーマンスの点でうまく機能しない可能性がありますが、それは見栄えがよく簡潔です。

ただし、条件がUPDATEステートメントでどのように再利用されるかを考えると、別のアプローチを取ることもできます。影響を受けるIDと新しい値を派生テーブルとして表し、結合で更新を使用します。

UPDATE
    Tests AS old
    INNER JOIN
    (
        SELECT 10 AS TestId, 25 AS TestSubId, 1000 AS TestScore, 2000 AS TestScore2
        UNION ALL
        SELECT 11, 22, 1100, 2100
    ) AS new
    ON old.TestId = new.TestId AND old.TestSubId = new.TestSubId
SET
    old.TestScore  = new.TestScore,
    old.TestScore2 = new.TestScore2
;

このように、new派生テーブルは、Testsのフィルターと、更新の新しい値のサプライヤーの両方として機能します。

6
Andriy M

in演算子を使用して2つの異なる列をフィルタリングすることはできません。この例では、標準の論理演算子を使用する必要があります。

UPDATE Tests SET
TestScore = CASE
    WHEN (TestId = 10 AND TestSubId = 25) THEN 1000
    WHEN (TestId = 11 AND TestSubId = 22) THEN 1100
END,
TestScore2 = CASE
    WHEN (TestId = 10 AND TestSubId = 25) THEN 2000
    WHEN (TestId = 11 AND TestSubId = 22) THEN 2100
END
WHERE (TestId = 10 AND TestSubId = 25)
  OR (TestId = 11 AND TestSubId = 22)
2
Rich Theobald