0

2 つのテーブルがあるとします。

CREATE TABLE state (
    id TINYINT,
    state CHAR(2),
    PRIMARY KEY (id)
);

CREATE TABLE valid_state (
    id INT,
    state CHAR(2), # or stateId TINYINT or whatever
    productId INT
);

製品が CA でしか販売できない場合、valid_state に 1 つのエントリがあります。すべての州で販売できる場合、valid_state にエントリはありません。どの州でも販売できない場合は、未定義の製品テーブルで製品を無効にする必要があります。

私の質問は次のとおりです。特定の製品の有効な状態をすべて選択するにはどうすればよいですか? 理想的には、valid_state から選択し、空かどうかを確認し、空である場合はすべての状態を返すだけです。残念ながら、これを行う方法がわかりません。

何か案は?

(また、fwiw、私はスキーマを設計していないので、変更を提案してもあまり役に立ちません)

4

2 に答える 2

1

これを実現する 1 つの方法は、UNIONandを使用することNOT EXISTSです。

SELECT DISTINCT S.Id, 
   S.State
FROM State S
   JOIN valid_state V ON S.State = V.State AND V.ProductId = @ProductId
UNION 
SELECT DISTINCT S.Id, 
   S.State
FROM State S
WHERE NOT EXISTS  (SELECT * FROM valid_state WHERE ProductId = @ProductId)

これがサンプルFiddleです。

幸運を。

于 2013-02-07T02:50:03.360 に答える
0

私は別のアプローチを思いつきました。

すべての状態を取得し、最初の LEFT JOIN で特定の製品に有効な状態をマークします。

2 番目の LEFT JOIN では、製品が有効であるすべての状態を取得して結合します。V.id = V2.id がなければ、valid_states * 2 行が返されますが、それを使用すると、必要なものだけが得られます。

SELECT S.Id, S.State
FROM state S
LEFT JOIN valid_state V
  ON V.state = S.state
    AND productId = @ProductId
LEFT JOIN (state S2, valid_state V2)
    ON V2.productId = @ProductId
        AND S2.state = S.state
WHERE V.id = V2.id OR V2.id IS NULL;

どっちがいいのかわからない。sgeddes の EXPLAIN は、3*3*3 行を調べているのに対し、私の場合は 3*3*3*3 を行っていることを示しています。しかし、sgeddes には EXPLAIN に 5 つの列があり (そのうちの 2 つは行に NULL があります)、「一時的な使用」、「結合バッファーの使用」、および「不可能な WHERE」があります。

何か案は?

于 2013-02-07T19:24:00.897 に答える