###実現したいこと
post_id=5,6が取得されてしまいますが、これをpost_id=5だけにし、post_id=6は除外したいです。
###発生している問題
NOT EXISTSを書いているのにpost_id=6が除外できません。
###テーブル設計
長くて申し訳ございませんが、以下6つのテーブルがあります。
CREATE TABLE posts (`post_id` int, `author_id` int, `parent_thread_id` int, `parent_comment_id` int, `kind` varchar(10), `text` varchar(1000), `date` datetime) ; INSERT INTO posts (`post_id`, `author_id`, `parent_thread_id`, `parent_comment_id`, `kind`, `text`, `date`) VALUES (1, 2, 0, 0, 'thread', '#青空 と #雲 が大好きなスレ', '2020-01-01 01:00:00'), (2, 2, 1, 0, 'comment', 'いい天気ですね', '2020-01-01 02:00:00'), (3, 1, 1, 2, 'reply', 'でも #明日 は #雨 です', '2020-01-01 03:00:00'), (4, 3, 0, 0, 'thread', '青い海で泳ぎたいスレ', '2020-01-01 04:00:00'), (5, 1, 0, 0, 'thread', '山の厳しさを教えたいスレ', '2020-01-01 05:00:00'), (6, 2, 5, 0, 'comment', '冬の山は #危険 ですよ', '2020-01-01 06:00:00'), (7, 3, 4, 0, 'comment', '日焼け止めが必要ですね', '2020-01-01 07:00:00'), (8, 3, 1, 0, 'comment', '私は太陽がすきです', '2020-01-01 08:00:00') ; CREATE TABLE tags (`tag_id` int, `tag_name` varchar(100)) ; INSERT INTO tags (`tag_id`, `tag_name`) VALUES (1, '明日'), (2, '青空'), (3, '危険'), (4, '雲'), (5, '雨') ; CREATE TABLE tag_relations (`relation_id` int, `post_id` int, `tag_id` int) ; INSERT INTO tag_relations (`relation_id`, `post_id`, `tag_id`) VALUES #post1がtag2とtag4を持っている (1, 1, 2), (2, 1, 4), #post3がtag5とtag1を持っている (3, 3, 5), (4, 3, 1), #post6がtag3を持っている (5, 6, 3) ; CREATE TABLE users (`user_id` int, `user_name` varchar(50)) ; INSERT INTO users (`user_id`, `user_name`) VALUES (1, 'Aさん'), (2, 'Bさん'), (3, 'Cさん') ; CREATE TABLE actions (`action_id` int, `actor_id` int, `target_kind` varchar(20), `target_id` int, `action_name` varchar(10)) ; INSERT INTO actions (`action_id`, `actor_id`, `target_kind`, `target_id`, `action_name`) VALUES (1, 1, 'user', 2, 'follow'), (2, 2, 'user', 1, 'block'), (3, 1, 'thread', 4, 'follow'), (4, 1, 'tag', 2, 'follow'), (5, 3, 'user', 2, 'keep'), (6, 2, 'comment', 2, 'keep'), (7, 1, 'tag', 3, 'follow') ; CREATE TABLE limiteds (`limited_id` int, `thread_id` int, `target_id` int) ; INSERT INTO limiteds (`limited_id`, `thread_id`, `target_id`) VALUES #thread1がuser3に公開されてる (1, 1, 3), #thread5がuser2とuser3に公開されてる (2, 5, 2), (3, 5, 3) ;
###該当のソースコード
下記ソースコードで、post_id=5だけにし、post_id=6は除外したいのです。
なぜなら、
post_id=6を投稿したのはauthor_id=2(user2)であり、
user2はuser1をblockしており(actionsテーブルのaction_id=2のレコードがその情報です)、
よってpost_id=6は
➉「user1をblockしてるuser」が投稿したthreadとcommentを除外
に該当するため、除外したいという理由です。
しかし、除外するために➉に書いているNOT EXISTSが効かず困っています。
/* user1のタイムラインに流すthreadとcommentを【A、B、C、D】に基づき取得する 【A】「投稿」と関係するものを取得 #➀「user1が投稿したthreadとcomment」を取得 #➁「user1が投稿したthread」へのcommentを取得 【B】「follow情報」を元に取得 #➂「user1がfollowしてるuser」が投稿したthreadとcommentを取得 #➃「user1がfollowしているthread」に投稿されたcommentを取得 #➄「user1がfollowしてるtag」を持つthreadとcommentを取得 #➅「user1がfollowしているtag」を持つthreadに投稿されたcommentを取得 【C】「公開されてるもの」だけ取得 #➆「user1に公開されてるthread」を取得 #➇「user1に公開されてるthread」へのcommentを取得 【D】「block関係」は除外 #➈「user1がblockしてるuser」が投稿したthreadとcommentを除外 #➉「user1をblockしてるuser」が投稿したthreadとcommentを除外 */ SELECT p.post_id, p.author_id, p.parent_thread_id, p.kind, p.text, p.date, t.tag_id, t.tag_name FROM posts p LEFT JOIN tag_relations r ON r.post_id=p.post_id LEFT JOIN tags t ON t.tag_id=r.tag_id #【A】「投稿」と関係するものを取得 WHERE ( #➀「user1が投稿したthreadとcomment」を取得 p.author_id=1 AND ( p.kind='thread' OR p.kind='comment' ) #➁「user1が投稿したthread」へのcommentを取得 OR p.parent_thread_id = ( SELECT p.post_id FROM posts p WHERE p.author_id=1 AND p.kind='thread' ) ) #【B】「follow情報」を元に取得 OR ( #➂「user1がfollowしてるuser」が投稿したthreadとcommentを取得 p.author_id = ( SELECT a.target_id FROM actions a WHERE a.actor_id=1 AND a.action_name='follow' AND a.target_kind='user' ) #➃「user1がfollowしているthread」に投稿されたcomment OR p.parent_thread_id IN ( SELECT a.target_id FROM actions a WHERE a.actor_id=1 AND a.action_name='follow' AND a.target_kind='thread' ) #➄「user1がfollowしてるtag」を持つthreadとcommentを取得 OR t.tag_id IN ( SELECT a.target_id FROM actions a WHERE a.actor_id=1 AND a.action_name='follow' AND a.target_kind='tag' ) #➅「user1がfollowしているtag」を持つthreadに投稿されたcomment OR p.parent_thread_id IN ( SELECT post_id FROM tag_relations r WHERE tag_id IN ( SELECT target_id FROM actions WHERE actor_id=1 AND action_name='follow' AND target_kind='tag' ) ) ) #【C】「公開されてるもの」だけ取得 AND( #➆「user1に公開されてるthread」を取得 p.post_id IN ( SELECT l.thread_id FROM limiteds l WHERE l.target_id=1 ) #➇「user1に公開されてるthread」へのcommentを取得 OR p.parent_thread_id IN ( SELECT l.thread_id FROM limiteds l WHERE l.target_id=1 ) ) #【D】「block関係」は除外 AND( #➈「user1がblockしてるuser」が投稿したthreadとcommentを除外 NOT EXISTS ( SELECT post_id FROM posts WHERE author_id=( SELECT target_id FROM actions WHERE action_name='block' AND actor_id=1 ) ) #➉「user1をblockしてるuser」が投稿したthreadとcommentを除外 OR NOT EXISTS ( SELECT post_id FROM posts WHERE author_id=( SELECT actor_id FROM actions WHERE action_name='block' AND target_id=1 ) ) ) #新しい順に10件取得 ORDER BY date DESC LIMIT 0, 10
###試したこと
NOT EXISTSが効かないので、以下のようにNOT INを使ってみましたが同じ結果で、他に除外系の方法がわかりません。
#【D】「block関係」は除外 AND( #➈「user1がblockしてるuser」が投稿したthreadとcommentを除外 p.author_id NOT IN ( SELECT target_id FROM actions WHERE action_name='block' AND actor_id=1 ) #➉「user1をblockしてるuser」が投稿したthreadとcommentを除外 OR p.author_id NOT IN ( SELECT actor_id FROM actions WHERE action_name='block' AND target_id=1 ) )
長いうえに素人の手探りなソースコードで見にくいかとは思いますが、どうぞ宜しくお願い致します。
回答2件
あなたの回答
tips
プレビュー