###前提
掲示板を作っていて、「対象スレッドの投稿者でない者」が投稿したコメントの有無を確認したいという目的がございます。
例えばスレッドID=1に、その投稿者以外がコメントしていた場合、「スレッド管理者以外のコメントがあります」といった表示をしたいイメージです。
###実現したいこと
現状は「①スレッドのIDが与えられるパターン」なのですが、
これを「②コメントのIDが与えられるパターン」のコードに変更したいです。
つまり
「スレッドIDで対象スレッドを決める」のではなく、
「コメントIDからそのコメントが投稿されたスレッドIDを得て、そのスレッドIDで対象スレッドを決める」という変更です。
###テーブル
テーブルにはすべての投稿が入るp_matters
があり、そのサブタイプとしてp_threads
やp_comments
があります。
SQL
1-- 投稿 (スーパータイプ) 2CREATE TABLE p_matters ( 3 `ID` int 4 ,`user_ID` int 5 ,`kind` int 6 ,`sentence` varchar(1000) 7 ,`created_at` DATETIME(6) 8 ,PRIMARY KEY (`ID`) 9 ,INDEX idx_p_matters_1 (`kind`) 10 ,CONSTRAINT fk_p_matters_1 FOREIGN KEY (user_ID) REFERENCES users (ID) # 2020/11/07 03:33 追記 11); 12INSERT INTO p_matters 13 (`ID`, `user_ID`, `kind`, `sentence`, `created_at`) 14VALUES 15 # thread は kind=1 で comment は kind=2 16 (1, 3, 1, '猫について語りましょう', '2020-01-01 12:00:00.123456'), 17 (2, 3, 1, '犬について語りましょう', '2020-01-02 12:00:00.123456'), 18 (3, 4, 2, '猫はいいです', '2020-01-03 12:00:00.123456'), 19 (4, 1, 2, 'たしかに猫は最高です', '2020-01-04 12:00:00.123456'), 20 (5, 2, 1, '鰐について語りましょう', '2020-01-05 12:00:00.123456'), 21 (6, 3, 2, '鰐は怖いです', '2020-01-06 12:00:00.123456'), 22 (7, 1, 2, '犬はやわらかいです', '2020-01-07 12:00:00.123456'), 23 (8, 3, 2, '猫は液体です', '2020-01-08 12:00:00.123456'), 24 (9, 2, 2, '猫は液体ではないです', '2020-01-09 12:00:00.123456'), 25 (10, 4, 2, '鰐は怖くないです', '2020-01-10 12:00:00.123456') 26; 27 28-- 投稿 (サブタイプ/スレッド) 29CREATE TABLE p_threads ( 30 `matter_ID` int 31 ,`title` varchar(100) 32 ,PRIMARY KEY (`matter_ID`) 33 ,CONSTRAINT fk_p_threads_1 FOREIGN KEY (`matter_ID`) REFERENCES p_matters(`ID`) # 2020/11/06 23:18 追記 34); 35INSERT INTO p_threads 36 (`matter_ID`, `title`) 37VALUES 38 (1, '猫スレ'), (2, '犬スレ'), (5, '鰐スレ') 39; 40 41-- 投稿 (サブタイプ/コメント) 42CREATE TABLE p_comments ( 43 `matter_ID` int 44 ,`thread_ID` int 45 ,PRIMARY KEY (`matter_ID`) 46 ,CONSTRAINT fk_p_comments_1 FOREIGN KEY (`matter_ID`) REFERENCES p_matters(`ID`) 47 ,CONSTRAINT fk_p_comments_2 FOREIGN KEY (`thread_ID`) REFERENCES p_threads(`matter_ID`) 48); 49INSERT INTO p_comments 50 (`matter_ID`, `thread_ID`) 51VALUES 52 (3, 1),(4, 1),(6, 5),(7, 2),(8, 1),(9, 1),(10, 5) 53;
###該当のソースコード
現状の「①スレッドのIDが与えられるパターン」がこちらです。
実行 → http://sqlfiddle.com/#!9/ec5910/2
SQL
1/* 2- 与えられる値 3スレッド ID=1 が与えられます 4 5- 実行したいSQL文 6その投稿者である user_ID=3 以外が投稿したコメントを取得します 7 8- 求める結果 9結果は ID=3,4,9 となります 10*/ 11 12# スレッドへのコメントを取得 13SELECT * 14FROM p_matters matters1 15 INNER JOIN p_comments comments 16 ON comments.matter_ID = matters1.ID 17 AND comments.thread_ID = 1 18 19# ただしそのコメントの投稿者は次を含まない 20WHERE matters1.user_ID NOT IN ( 21 22 # 同スレッドの投稿者 23 SELECT matters2.user_ID 24 FROM p_matters matters2 25 LEFT JOIN p_threads threads 26 ON threads.matter_ID = matters2.ID 27 WHERE threads.matter_ID = 1 28)
###試したこと
上記を「②コメントのIDが与えられるパターン」のコードに変更したいわけで次のように試しました。
上記はスレッドIDが与えられますが、こちらはコメントIDしか与えられないため、対象スレッドを判断するためにSELECT
を増やさないといけないと思います。
一応できはしたのですが…
SELECT
をこうして増やしますと# ここでスレッド ID=1 を取得
というSELECT
が2か所になってしまい、この重複に冗長さを覚えています。
実行 → http://sqlfiddle.com/#!9/ec5910/4
sql
1/* 2- 与えられる値 3コメント ID=3 が与えられます 4 5- 実行したいSQL文 6そのスレッドである ID=1 を取得し 7その投稿者である user_ID=3 以外が投稿したコメントを取得します 8 9- 求める結果 10結果は ID=3,4,9 となります 11*/ 12 13# スレッドへのコメントを取得 14SELECT * 15FROM p_matters matters1 16 INNER JOIN p_comments comments 17 ON comments.matter_ID = matters1.ID 18 AND comments.thread_ID = ( 19 # ここでスレッド ID=1 を取得 20 SELECT thread_ID 21 FROM p_comments 22 WHERE matter_ID = 3 23 ) 24 25# ただしそのコメントの投稿者は次を含まない 26WHERE matters1.user_ID NOT IN ( 27 28 # 同スレッドの投稿者 29 SELECT matters2.user_ID 30 FROM p_matters matters2 31 LEFT JOIN p_threads threads 32 ON threads.matter_ID = matters2.ID 33 WHERE threads.matter_ID = ( 34 # ここでスレッド ID=1 を取得 35 SELECT thread_ID 36 FROM p_comments 37 WHERE matter_ID = 3 38 ) 39)
改めまして、上記「②コメントのIDが与えられるパターン」のコードにつきまして、この冗長さを回避するとしたらどんな書き方が良いでしょうか。
アドバイスよろしくお願い致します。
回答1件
あなたの回答
tips
プレビュー