1

指定されたフィールドを持つ2つのテーブルがあります

  1. 高校生

    • 名前
    • 学年
    • ID
  2. いいね

    • id1
    • id2

HighSchooler は高校生に関する情報を保持し、Likes は高校の誰が誰を好きかを示す関係テーブルです。id1 の生徒は id2 の生徒が好きです。一方向の関係 (John が Lucy を好きで、Lucy が John を好きではない) と双方向の関係 (Albert が Sandra を好きで、Sandra も Albert が好き) の両方があります。

双方向の関係にある名前を持つ 2 つの列を返すクエリが必要です。つまり、A が B を好み、B が A を好む場合、サンプルの結果セットは次のようになります。

name | name
A       B

私はそれをいじってこのクエリを思いつきましたが、理解できず、最適だとは思いません。

SELECT DISTINCT a.name, b.name 
FROM Highschooler a, Highschooler b, Likes l1 
JOIN Likes l2 on l1.ID1=l2.ID2 
WHERE a.ID=l1.ID2 AND b.ID=l1.ID1 AND a.ID=l2.ID1 AND a.ID > b.ID;
4

3 に答える 3

3

ルールを使用して Likes テーブルをそれ自体と結合してみてください(l1.id1 = l2.id2) and (l1.id2 = l2.id1)

例:

SELECT
   a.name AS a_name,
   b.name AS b_name
FROM
   HighSchooler AS a
   INNER JOIN Likes AS l1
      ON (a.id = l1.id1)
   INNER JOIN Likes AS l2
      ON ((l1.id1 = l2.id2) AND (l1.id2 = l2.id1) AND (l1.id1 > l2.id1))
   INNER JOIN HighSchooler AS b
      ON (l2.id1 = b.id)

http://sqlfiddle.com/#!2/44a07/6

于 2013-03-09T21:46:46.980 に答える
1

重要な自己結合は、Likes テーブルへの 2 つの参照の間です。次に、これを HighSchoolers テーブルに 2 回結合して、2 人の名前を取得する必要があります。

ステップ 1 互いに好きな ID のペア

SELECT l1.id1, l1.id2
  FROM Likes AS l1
  JOIN Likes AS l2
    ON l1.id1 = l2.id2 AND l1.id2 = l2.id1;

これにより、互いに好きな ID のペアのリストが得られます。

ステップ 2 繰り返しなしでお互いが好きな ID のペア

唯一の問題は、各ペアが 2 回与えられることです。したがって、コツは、2 つの行のうちの 1 つのid1値が値より小さいことに注意することid2です。おそらく有益な副作用として、これは自分を好きな人を排除します.

SELECT l1.id1, l1.id2
  FROM Likes AS l1
  JOIN Likes AS l2
    ON l1.id1 = l2.id2 AND l1.id2 = l2.id1;
 WHERE l1.id1 < l1.id2

ステップ 3 それぞれが好きな名前のペア

次に、名前で整理します。

SELECT h1.name AS name1, h2.name AS name2
  FROM (SELECT l1.id1, l1.id2
          FROM Likes AS l1
          JOIN Likes AS l2
            ON l1.id1 = l2.id2 AND l1.id2 = l2.id1
         WHERE l1.id1 < l1.id2
       ) AS p
  JOIN HighSchoolers AS h1 ON p.id1 = h1.id
  JOIN HighSchoolers AS h2 ON p.id2 = h2.id

p「ペア」のニーモニックです。

于 2013-03-09T22:39:48.037 に答える
1

あなたのクエリは正しいですが、あなたが言ったように最適ではないテーブルのデカルト積を使用しています。a のすべての行と b のすべての行を書き込むselect * from a,bと、size(a)*size(b) 行を持つ新しいテーブルが形成されます。3 つのテーブルでそれを行っているため、巨大なテーブルを作成し、そこから必要な行をいくつか選択します。内部結合はこれをより効率的に行うことができます。

SELECT
a.name AS name_a, b.name AS name_b
FROM
HighSchooler AS a
INNER JOIN Likes AS l1
ON a.id = l1.id1
INNER JOIN Likes AS l2
ON l1.id1 = l2.id2 AND l1.id2 = l2.id1 AND l1.id1 < l1.id2
INNER JOIN HighSchooler AS b
ON l1.id2 = b.id;

フィドルを参照してください:

于 2013-03-09T22:26:18.807 に答える