はじめに
根本的な質問の仕方の問題点については、質問への追記・修正の依頼欄で皆さん色々アドバイスしてくれていると思いますので、そちらをご参照ください。
下記に記載のクエリの解説と動作確認用クエリを読みながら、分からない部分は調べてもらえば理解も深まると思います。
文章レベルでの解説は敢えて書いていないので、SQLの機能を1つ1つ分解して咀嚼してみてください。
質問者さんのSQL理解に少しでも役立てば幸いです。
キーワード
- 疑問符プレースホルダ
- SQLインジェクション
- NOT EXISTS
- 相関サブクエリ(相関副問合せ)
クエリ解説
sql
1/* 1. メインクエリ */
2SELECT
3 u.*
4FROM
5 users AS u
6WHERE
7 /* 2.でも3.でも1件も返ってこない = ブロックしていない/されていないユーザーを絞り込む */
8 NOT EXISTS (
9 /* 2. 相関サブクエリ */
10 SELECT 1 -- blocked_usersテーブルのカラムの値は不要なので固定値をSELECT
11 FROM blocked_users AS bu
12 /* メインクエリで取得したusers.idが?で指定したIDをブロックしているか検索 */
13 WHERE bu.user_id = u.id AND bu.user_blocked_id = ?
14 )
15 AND NOT EXISTS (
16 /* 3. 相関サブクエリ */
17 SELECT 1
18 FROM blocked_users AS bu
19 /* メインクエリで取得したusers.idが?で指定したIDにブロックされているか検索 */
20 WHERE bu.user_blocked_id = u.id AND bu.user_id = ?
21 )
22;
動作確認用クエリ
クエリの実行結果を確認するためだけに作ったのでテーブル定義は適当です。
sql
1CREATE TABLE IF NOT EXISTS users (
2 id INT PRIMARY KEY AUTO_INCREMENT,
3 name VARCHAR(64)
4);
5
6CREATE TABLE IF NOT EXISTS blocked_users (
7 user_id INT COMMENT 'ブロックしたユーザのID',
8 user_blocked_id INT COMMENT 'ブロックされたユーザのID'
9);
10
11TRUNCATE TABLE users;
12TRUNCATE TABLE blocked_users;
13
14INSERT INTO users(id, name)
15VALUES
16 (1, 'ユーザ'),
17 (2, 'ブロックしたユーザ'),
18 (3, 'ブロックされたユーザ'),
19 (4, '無関係なユーザ');
20
21INSERT INTO blocked_users(user_id, user_blocked_id)
22VALUES
23 (1, 2),
24 (3, 1);
25
26SELECT
27 u.*
28FROM
29 users AS u
30WHERE
31 NOT EXISTS (
32 SELECT 1
33 FROM blocked_users AS bu
34 WHERE bu.user_id = u.id AND bu.user_blocked_id = 1
35 )
36 AND NOT EXISTS (
37 SELECT 1
38 FROM blocked_users AS bu
39 WHERE bu.user_blocked_id = u.id AND bu.user_id = 1
40 )
41;
実行結果
+----+----------------+
| id | name |
+----+----------------+
| 1 | ユーザ |
| 4 | 無関係なユーザ |
+----+----------------+
2 rows in set
Time: 0.014s