質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

phpMyAdmin

phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

2回答

3692閲覧

SQLで「SELECTの結果」を連結したい

ikatako

総合スコア270

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

phpMyAdmin

phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2020/02/10 20:09

###実現したいこと
「スレッドへのコメントリスト」と「お気に入りリスト」を連結したいです。

コメントへは添付データがありうるので、「コメントへの添付データをお気に入りしているかどうか」も、コメントと一緒に表示したいためです。

イメージ説明

それぞれ別々のSELECTはできており、あとは連結だけなので簡単かと思ったのですが躓いてしまいました。

以下とても長い内容になってしまいましたが、ご覧いただけましたら幸いでございます。

###対象のテーブル
後述するすべてのSQL fiddleのテーブルのCREATE TABLEを念のため掲載いたします。(SQL fiddleにあるものと同じなのでご覧いただかなくとも結構です。)

SQL

1# jp_actions 2# アクションのテーブル 3CREATE TABLE jp_actions 4 (action_id int, action_name text, action_date text, actor_id int, target_id int, target_type text, target_country_code text) 5; 6INSERT INTO jp_actions 7 (action_id, action_name, action_date, actor_id, target_id, target_type, target_country_code) 8VALUES 9 (1, 'follow', '2020-01-01 01:00:00', 1, 3, 'user', 'jp'), 10 (2, 'favorite', '2020-02-02 02:00:00', 1, 4, 'drama', 'zh'), 11 (3, 'favorite', '2020-03-03 03:00:00', 1, 3, 'user', 'jp'), 12 (4, 'favorite', '2020-04-04 04:00:00', 2, 5, 'user', 'jp'), 13 (5, 'favorite', '2020-05-05 05:00:00', 1, 7, 'user', 'jp'), 14 (6, 'follow', '2020-06-06 06:00:00', 1, 2, 'user', 'jp'), 15 (7, 'follow', '2020-07-07 07:00:00', 1, 7, 'user', 'jp'), 16 (8, 'block', '2020-08-08 08:00:00', 1, 5, 'user', 'jp'), 17 (9, 'favorite', '2020-09-09 09:00:00', 1, 5, 'user', 'jp'), 18 (10, 'favorite', '2020-10-10 10:00:00', 1, 5, 'movie', 'en'), 19 (11, 'favorite', '2020-11-11 11:00:00', 1, 3, 'user', 'en'), 20 (12, 'favorite', '2020-12-12 12:00:00', 1, 3, 'thread','jp') 21; 22 23# country_contents 24# コンテンツのテーブル 25CREATE TABLE country_contents 26 (content_id int, content_type text, country_code text, content_title text) 27; 28INSERT INTO country_contents 29 (content_id, content_type, country_code, content_title) 30VALUES 31 (1, 'user', 'en', 'smith'), 32 (2, 'manga', 'zh', '砂輿海之歌'), 33 (3, 'user', 'ko', '지안'), 34 (4, 'drama', 'en', 'Mr.ROBOT'), 35 (5, 'movie', 'en', 'Avator'), 36 (6, 'movie', 'ru', 'Хардкор'), 37 (7, 'drama', 'zh', '大秦帝国') 38; 39 40# jp_threads 41# 掲示板のテーブル 42CREATE TABLE jp_threads 43 (thread_id int, thread_text text, thread_theme text, allowed_user_ids text) 44; 45INSERT INTO jp_threads 46 (thread_id, thread_text, thread_theme, allowed_user_ids) 47VALUES 48 (1, 'かわいい猫の画像スレ', '画像のこと', '"[1,2,3]"'), 49 (2, '結婚できない女のスレ', '結婚のこと', '"[2,3]"'), 50 (3, 'お酒に合う音楽のスレ', '音楽のこと', '"[1,3]"') 51; 52 53# jp_voices 54# コメントや返信のテーブル 55CREATE TABLE jp_voices 56 (voice_id int, thread_id int, parent_id int, voice_type text, voice_text text, up int, down int, attach_id int, attach_type text, attach_country text) 57; 58INSERT INTO jp_voices 59 (voice_id, thread_id, parent_id, voice_type, voice_text, up, down, attach_id, attach_type, attach_country) 60VALUES 61 (1, 1, 0, 'comment', '元気ですか?', 10, 15, 0, '', ''), 62 (2, 1, 1, 'reply', '元気ですよ!', 29, 28, 4, 'drama', 'en'), 63 (3, 2, 0, 'comment', '生きてますか?', 31, 37, 3, 'user', 'ko'), 64 (4, 2, 3, 'reply', '生きてますよ!', 46, 40, 0, '', ''), 65 (5, 2, 3, 'reply', '死んでますよ!', 52, 53, 0, '', ''), 66 (6, 2, 5, 'reply', '死んでますか!?', 69, 60, 0, '', ''), 67 (7, 1, 0, 'comment', '愛してますか?', 78, 73, 3, 'user', 'jp') 68; 69 70# jp_users 71# ユーザーのテーブル 72CREATE TABLE jp_users 73 (user_id int, unique_name text, nick_name text) 74; 75INSERT INTO jp_users 76 (user_id, unique_name, nick_name) 77VALUES 78 (1, 'ichiro', '田中一郎'), 79 (2, 'jiro', '田中二郎'), 80 (3, 'saburo', '田中三郎'), 81 (4, 'shiro', '田中四郎'), 82 (5, 'goro', '山田五郎'), 83 (6, 'rokuro', '山田六郎'), 84 (7, 'nanaro', '山田七郎') 85; 86

###「スレッドへのコメントリスト」
まずこちらが「スレッドへのコメントリスト」になりまして、thread_id=1へのコメントを取得します。

下記コードを実行する

SQL

1select * 2from 3jp_voices 4where 5thread_id=1 and voice_type='comment'

###「お気に入りリスト」
そしてこちらが「お気に入りリスト」になりまして、user_id=1さんのfavoriteを取得します。

下記コードを実行する

SQL

1 select 2 case 3 when actions.target_type='user' and actions.target_country_code='jp' 4 then users.user_id 5 else contents.content_id 6 end as content_id 7 , case 8 when actions.target_type='user' and actions.target_country_code='jp' 9 then users.nick_name 10 else null 11 end as nick_name 12 , case 13 when actions.target_type='thread' and actions.target_country_code='jp' 14 then threads.thread_text 15 else null 16 end as thread_text 17 , case 18 when (actions.target_type='user' and actions.target_country_code='jp') or actions.target_type='thread' 19 then null 20 else contents.content_title 21 end as content_title 22 , case 23 when (actions.target_type='user' and actions.target_country_code='jp') or actions.target_type='thread' 24 then actions.target_type 25 else content_type 26 end as content_type 27 , case 28 when (actions.target_type='user' and actions.target_country_code='jp') or actions.target_type='thread' 29 then actions.target_country_code 30 else contents.country_code 31 end as country_code 32 , max( case when 33 actions.action_name='follow' then actions.action_date end 34 ) as follow_date 35 , max( case when 36 actions.action_name='favorite' then actions.action_date end 37 ) as favorite_date 38 39 from jp_actions actions 40 41 # join 42 left join jp_threads threads 43 on actions.target_id=threads.thread_id 44 left join jp_users users 45 on actions.target_id=users.user_id 46 left join country_contents contents 47 on actions.target_id=contents.content_id 48 49 # 彼がactor_idであるfavoriteを指定 50 where actions.actor_id=1 51 # favorite_dateとfollow_dateが欲しいので以下を指定 52 and actions.action_name in ('favorite', 'follow') 53 and exists( 54 select 0 from jp_actions 55 where target_id=actions.target_id and action_name='favorite' 56 ) 57 # 彼とblock関係にあるjpのuserを除外 58 and not exists( 59 select 0 from jp_actions 60 where target_type='user' and target_country_code='jp' and action_name='block' 61 and target_id=actions.target_id and actions.target_type='user' 62 and actor_id=1 63 ) 64 65 group by actions.target_id, actions.target_type, actions.target_country_code 66 order by favorite_date desc

###試したこと
SELECTの結果同士の連結になるかと思いますので、以下の方法を見つけました

SQL

1SELECT * 2FROM 3[テーブルA] 4INNER JOIN 5 ( 6 SELECT [項目B] 7 FROM XX 8 WHERE XX 9 )AS [結果セットC] 10ON [テーブルA].[項目C] = [結果セットC].[項目B] 11WHERE 12[テーブルA].[項目D] = 'XX'

そしてこの方法を「スレッドへのコメントリスト」と「お気に入りリスト」に適用したのが下記ですが、実現することができませんでした。

下記コードを実行する → 実現できずエラーでした

SQL

1SELECT * 2FROM 3jp_voices 4INNER JOIN 5 ( 6 # 「お気に入りリスト」のコードをここにコピペ 7 )AS list 8ON jp_voices.attach_id=list.content_id 9WHERE 10jp_voices.parent_thread_id=1 and voice_type='comment'

###補足情報(FW/ツールのバージョンなど)
phpMyAdmin(4.8.5)で、MySQL(10.0.33-MariaDB)を使っています。

冒頭の画像のような連結のために修正すべき箇所をご指導いただけませんでしょうか。
どうぞ宜しくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2020/02/10 21:13

CREATE TABLE文(テーブル定義)とサンプルデータのINSERT文もあったほうがこちらも確認と検証がしやすいのですけど・・・。
ikatako

2020/02/11 14:18

m.ts10806さん、掲載したつもりでしたが、すみません、質問が読みにくかったですよね。
ikatako

2020/02/11 14:19

Orlofskyさん、大変勉強になりました。ありがとうございます。
m.ts10806

2020/02/11 20:04

ごめんなさい。こちらの見落としでした。
ikatako

2020/02/11 23:52

m.ts10806さん、いえ気にしないでください。あちらの質問とあわせてまた何かあれば遠慮なく仰ってください。
guest

回答2

0

単純にJOINしました。

sql

1select * from jp_voices 2inner join 3( select 4 case 5 when actions.target_type='user' and actions.target_country_code='jp' 6 then users.user_id 7 else contents.content_id 8 end as content_id 9 , case 10 when actions.target_type='user' and actions.target_country_code='jp' 11 then users.nick_name 12 else null 13 end as nick_name 14 , case 15 when actions.target_type='thread' and actions.target_country_code='jp' 16 then threads.thread_text 17 else null 18 end as thread_text 19 , case 20 when (actions.target_type='user' and actions.target_country_code='jp') or actions.target_type='thread' 21 then null 22 else contents.content_title 23 end as content_title 24 , case 25 when (actions.target_type='user' and actions.target_country_code='jp') or actions.target_type='thread' 26 then actions.target_type 27 else content_type 28 end as content_type 29 , case 30 when (actions.target_type='user' and actions.target_country_code='jp') or actions.target_type='thread' 31 then actions.target_country_code 32 else contents.country_code 33 end as country_code 34 , max( case when 35 actions.action_name='follow' then actions.action_date end 36 ) as follow_date 37 , max( case when 38 actions.action_name='favorite' then actions.action_date end 39 ) as favorite_date 40 from jp_actions actions 41 # join 42 left join jp_threads threads 43 on actions.target_id=threads.thread_id 44 left join jp_users users 45 on actions.target_id=users.user_id 46 left join country_contents contents 47 on actions.target_id=contents.content_id 48 49 # 彼がactor_idであるfavoriteを指定 50 where actions.actor_id=1 51 # favorite_dateとfollow_dateが欲しいので以下を指定 52 and actions.action_name in ('favorite', 'follow') 53 and exists( 54 select 0 from jp_actions 55 where target_id=actions.target_id and action_name='favorite' 56 ) 57 # 彼とblock関係にあるjpのuserを除外 58 and not exists( 59 select 0 from jp_actions 60 where target_type='user' and target_country_code='jp' and action_name='block' 61 and target_id=actions.target_id and actions.target_type='user' 62 and actor_id=1 63 ) 64 group by 1,2,3,4,5,6 65) AS list 66ON jp_voices.attach_id=list.content_id 67and jp_voices.attach_type=list.content_type 68and jp_voices.attach_country=list.country_code 69where jp_voices.thread_id=1 and jp_voices.voice_type='comment' 70; 71

メモリ消費軽減SQLを作成してみました

sql

1select 2 case 3 when actions.target_type='user' and actions.target_country_code='jp' 4 then users.user_id 5 else contents.content_id 6 end as content_id 7 , case 8 when actions.target_type='user' and actions.target_country_code='jp' 9 then users.nick_name 10 else null 11 end as nick_name 12 , case 13 when actions.target_type='thread' and actions.target_country_code='jp' 14 then threads.thread_text 15 else null 16 end as thread_text 17 , case 18 when (actions.target_type='user' and actions.target_country_code='jp') or actions.target_type='thread' 19 then null 20 else contents.content_title 21 end as content_title 22 , case 23 when (actions.target_type='user' and actions.target_country_code='jp') or actions.target_type='thread' 24 then actions.target_type 25 else content_type 26 end as content_type 27 , case 28 when (actions.target_type='user' and actions.target_country_code='jp') or actions.target_type='thread' 29 then actions.target_country_code 30 else contents.country_code 31 end as country_code 32 , max( case when 33 actions.action_name='follow' then actions.action_date end 34 ) as follow_date 35 , max( case when 36 actions.action_name='favorite' then actions.action_date end 37 ) as favorite_date 38 , jp_voices.voice_id 39 , jp_voices.thread_id 40 , jp_voices.parent_id 41 , jp_voices.voice_type 42 , jp_voices.voice_text 43 , jp_voices.up 44 , jp_voices.down 45 from jp_actions actions 46 # join 47 left join jp_threads threads 48 on actions.target_id=threads.thread_id 49 left join jp_users users 50 on actions.target_id=users.user_id 51 left join country_contents contents 52 on actions.target_id=contents.content_id 53 join jp_voices 54 on jp_voices.attach_id=actions.target_id 55 and jp_voices.attach_type=case 56 when (actions.target_type='user' and actions.target_country_code='jp') or actions.target_type='thread' 57 then actions.target_type else content_type end 58 and jp_voices.attach_country=case 59 when (actions.target_type='user' and actions.target_country_code='jp') or actions.target_type='thread' 60 then actions.target_country_code 61 else contents.country_code 62 end 63 and jp_voices.thread_id=1 and jp_voices.voice_type='comment' 64 65 # 彼がactor_idであるfavoriteを指定 66 where actions.actor_id=1 67 # favorite_dateとfollow_dateが欲しいので以下を指定 68 and actions.action_name in ('favorite', 'follow') 69 and exists( 70 select 0 from jp_actions 71 where target_id=actions.target_id and action_name='favorite' 72 ) 73 # 彼とblock関係にあるjpのuserを除外 74 and not exists( 75 select 0 from jp_actions 76 where target_type='user' and target_country_code='jp' and action_name='block' 77 and target_id=actions.target_id and actions.target_type='user' 78 and actor_id=1 79 ) 80 group by 1,2,3,4,5,6,9,10,11,12,13,14,15;

投稿2020/02/11 02:13

編集2020/02/11 23:47
amura

総合スコア333

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ikatako

2020/02/11 13:51

ありがとうございます。メモリの食いすぎということで実現できませんでした。スマートな方法があればいいのですが、長くなると難しいですよね。 ところでgroup byの123456というのは何を意味しているのですか?
ikatako

2020/02/12 13:32

メモリ消費軽減SQL、ありがとうございます。やはりgroup byの数字が理解できないので、hoshi-takanoriさんの理解できるコードに魅力を感じます。もしお時間ございましたら簡単にご説明願えませんでしょうか。
amura

2020/02/12 14:10

group by の数字はselectのカラムの順番号です。caseなどで編集されている場合に結果を元にグループ化を行ってくれます。実際はSQLのコンパイル時にselectに書かれたものをそのまま順番に並べて展開しています。つまり番号を指定して、実行時に対応するSQLを展開して下さいの指定です。 7,8が無いのはMAXに対応する番号です(groupbyの対象外)
ikatako

2020/02/13 21:47

groupbyをマスターしていないので難しいですね。尚、メモリ消費軽減SQLの方も残念ながらメモリの食いすぎというエラーになってしまいましたが、そのselectのまとめ方が大変勉強になりました。ありがとうございます。
guest

0

ベストアンサー

WHERE の条件は jp_voices テーブルに対するものなので、こんな感じでどうでしょうか?

SQL

1SELECT * 2FROM 3 ( 4 select * 5 from jp_voices 6 where thread_id=1 and voice_type='comment' 7 ) AS voices 8INNER JOIN 9 ( 10 # 「お気に入りリスト」のコードをここにコピペ 11 ) AS list 12ON voices.attach_id=list.content_id

INNER JOIN だとお気に入りリストに入ってないコメントは消えてしまうので、OUTER JOIN の方がいいかも。

投稿2020/02/10 21:05

hoshi-takanori

総合スコア7895

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ikatako

2020/02/12 18:32 編集

どうもありがとうございます。質問の図説のようにはなりませんでしが、良いヒントを頂戴致しました。参考にさせて頂きます。
ikatako

2020/02/12 18:31 編集

ご回答のコードを ・最後のONに条件をいくつか追加 ・LEFT OUTER JOINへ変更 とすることによって、図説のように連結できました。 http://sqlfiddle.com/#!9/78c942/30
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問