1

このスキーマを考えると:

CREATE TABLE t (
  id int,
  name varchar(200),
  primary key (id)
);

CREATE TABLE t2 (
  id int,
  name varchar(200),
  primary key (id)
);

CREATE TABLE rel (
  id1 int,
  id2 int,
  value int,
  primary key (id1, id2),
  foreign key (id1) REFERENCES t(id),
  foreign key (id2) REFERENCES t2(id)
);

tとの複数の関係を満たす行をクエリするにはどうすればよいt2ですか? これは十分に簡単に聞こえますが、この場合のベスト プラクティスが何であるかはわかりません。クエリでよりよく説明します。

SELECT t.id, t.name
FROM t
INNER JOIN rel ON (t.id = rel.id1)
INNER JOIN t2 ON (t2.id = rel.id2)
WHERE (rel.id2 = 1 AND rel.value = 1)

上記は、1 つの関係を満たす行を見つける必要がある場合にうまく機能します。でも今:

SELECT t.id, t.name
FROM t
INNER JOIN rel ON (t.id = rel.id1)
INNER JOIN t2 ON (t2.id = rel.id2)
WHERE (rel.id2 = 1 AND rel.value = 1)
AND (rel.id2 = 2 AND rel.value = 2)

2 つのリレーションシップでは、結合された行が 1 つの行に 2 つの異なるリレーションシップを持つことはないため、このクエリは機能しません。したがって、常に0行が返されます。

私がこれまで使用してきたソリューションは、リレーションからの結果セットでt.idあるを探しています。IN

SELECT t.id, t.name
FROM t
WHERE (t.id IN (SELECT id1 FROM rel WHERE rel.id2 = 1 AND rel.value = 1))
AND (t.id IN (SELECT id1 FROM rel WHERE rel.id2 = 2 AND rel.value = 2))

これはうまくいきますが、もっと良い方法はありませんか?SQL を書きすぎていて、アイテムごとに 1 つのサブクエリを実行するのは、とても単純なことに対してやり過ぎのように感じます。

これがSQLフィドルです

4

2 に答える 2

2

これを関係分割と呼びます。

SELECT   t.id, t.name
FROM     t 
         INNER JOIN rel
            ON t.id = rel.id1
WHERE    rel.id2 IN (1,2) AND
         rel.value = 1
GROUP BY t.id, t.name
HAVING   COUNT(rel.id2) = 2
于 2013-01-22T11:55:30.627 に答える
2

問題を単純化しすぎている可能性がありますが、where 句で を に変更して、特定の基準の関係の数を取得するために使用ANDすることはできませんか。例えばORGROUP BY/HAVING

SELECT  t.id, t.name
FROM    t
        INNER JOIN rel 
            ON t.id = rel.id1
        INNER JOIN t2 
            ON t2.id = rel.id2
WHERE   (rel.id2 = 1 AND rel.value = 1)
OR      (rel.id2 = 2 AND rel.value = 1)
GROUP BY t.Id, t.Name
HAVING COUNT(*) = 2;

where句を次のように書き直しますが:

WHERE   rel.Value = 1 
AND     rel.ID2 IN (1, 2)

編集

上記の where 句を編集した質問で書き直すことはもうありません。それはなるだろう

WHERE   (rel.id2 = 1 AND rel.value = 1)
OR      (rel.id2 = 2 AND rel.value = 2)
于 2013-01-22T11:57:37.190 に答える