あなたの構造を考えると、それを行う1つの方法は次のとおりです。
SELECT users.id, users.name
FROM relations
INNER JOIN users ON relations.user2 = users.id
WHERE relations.user1 = 1
UNION ALL
SELECT users.id, users.name
FROM relations
INNER JOIN users ON relations.user1 = users.id
WHERE relations.user2 = 1
これは、重複する行を含めないように注意を払っていることを前提としています。user1
これを確認する 1 つの方法は、常に より小さくなければならない制約を確立することuser2
です。複合一意キー ( user1
、user2
) を使用します。これはおそらく PK です。
この場合、格納されるデータは次のように変更されます。
ユーザー1 ユーザー2
1 2
1 3
1 5
理解を完全にするために、あなたが望むことを達成するための他の方法があります. このクエリは、ユニオンが最外層ではなく派生テーブルで取得されることを除いて、最初のクエリとほとんど同じです。ただし、優れたクエリ オプティマイザーは 2 つを同じものとして認識する場合があります。
SELECT users.id, users.name
FROM users
INNER JOIN
(
SELECT user1 AS id FROM relations WHERE user2 = 1
UNION ALL
SELECT user2 AS id FROM relations WHERE user1 = 1
) friends ON users.id = friends.id
または、次のような本当に醜いクエリで、あなたの試みに似ています。これは間違いなく遅くなり、お勧めしません (CASE
とOR
は余分な処理ステップであり、処理が遅くなり、インデックスの使用が無効になる可能性があります)。
SELECT users.id, users.name
FROM users
INNER JOIN
(
SELECT CASE WHEN user1 = 1 THEN user2 ELSE user1 END AS id
FROM relations
WHERE user1 = 1 OR user2 = 1
) friends ON users.id = friends.id
これらのクエリの結果を見て、EXPLAIN
どれが最適かを判断できます。