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

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

新規登録して質問してみよう
ただいま回答率
85.35%
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回答

1944閲覧

SQLで1つのテーブルから2つのデータを並べて取得したい

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/06 22:52

###実現したいこと
該当のテーブルaction_tableから、
user_id=1が実行したfavoriteを取得する。
favorite_dateを入れる。
follow_dateを入れる。
という風に取得したいです。

###発生している問題
➀と➁はできましたが、➂ができません。
###該当のテーブル
以下action_tableになります。

SQL

1CREATE TABLE action_table 2 (`action_id` int, `action_name` text, `action_date` text, `actor_id` int, `target_id` int, `target_type` text) 3; 4INSERT INTO action_table 5 (`action_id`, `action_name`, `action_date`, `actor_id`, `target_id`, `target_type`) 6VALUES 7 (1, 'follow', '2020-01-01 01:01:01', 1, 3, 'user'), 8 (2, 'favorite', '2020-02-02 02:02:02', 1, 4, 'user'), 9 (3, 'favorite', '2020-03-03 03:03:03', 1, 3, 'user'), 10 (4, 'block', '2020-04-04 04:04:04', 4, 1, 'user'), 11 (5, 'follow', '2020-05-05 05:05:05', 1, 2, 'user'), 12 (6, 'favorite', '2020-06-06 06:06:06', 1, 5, 'user') 13;

###現状のソースコード
問題が発生するソースコードです。

ソースコードを実行する

実行していただくとfollow_datenullになってしまっていると思います。

SQL

1 select favorite.target_id 2 , case when 3 favorite.action_name='follow' 4 then favorite.action_date else null end 5 as follow_date 6 , case when 7 favorite.action_name='favorite' 8 then favorite.action_date else null end 9 as favorite_date 10 11 from action_table favorite 12 13 where favorite.actor_id=1 and favorite.action_name='favorite' 14 15 group by favorite.target_id

###試したこと
favoriteだけに限定せず、そしてgroup byをやめるという下記2つの変更を試みました。

変更したソースコードを実行する

必要なレコードがそろっていることが確認できました。
これをうまくgroup byすればよさそうに思えます。

SQL

1 where favorite.actor_id=1 and favorite.action_name='favorite' 2 ↓ 変更 3 where favorite.actor_id=1

SQL

1 group by favorite.target_id 2 ↓ 変更 3 # group by favorite.target_id

これら必要なレコードからnullのものを除外してみたらどうかと思い下記のようにcount()を使ったのですが、

count()を使ったソースコードを実行する

なぜか取得できたのは「3だけ」となってしまいました。(count()max()にしても同じでした)

「1」がfavoriteしているのは「3だけ」でなく「4・3・5」なのでそのレコードを取得したいのですが。

SQL

1 select favorite.target_id 2 , case when 3 favorite.action_name='follow' 4 then favorite.action_date else null end 5 as follow_date 6 , case when 7 favorite.action_name='favorite' 8 then favorite.action_date else null end 9 as favorite_date 10 11count()を使うように変更 12 13 select favorite.target_id 14 , count( case when 15 favorite.action_name='follow' 16 then favorite.action_date else null end 17 ) as follow_date 18 , count( case when 19 favorite.action_name='favorite' 20 then favorite.action_date else null end 21 ) as favorite_date

###補足情報(FW/ツールのバージョンなど)

phpMyAdmin(4.8.5)で、MySQL(10.0.33-MariaDB)を使っています。
宜しくお願い致します。

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

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

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

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

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

Orlofsky

2020/02/06 23:02

過去の質問を解決してから進めては?
ikatako

2020/02/06 23:25

過去の質問を解決するための質問がこれなので苦笑 少しずつですが進ませてください。
yambejp

2020/02/07 01:30

想定する結果を例示できますか?
ikatako

2020/02/07 12:01

結果の例示の件、申し訳ございません。今回は解決していただきましたので割愛致しますが、以後気を付けます。
guest

回答2

0

ベストアンサー

group byで指定している項目以外は、集計(max()とか、count()とか)でないと通常はエラーです。
mysqlでは設定により、集計を指定しなくても忖度しますがその値は不定(保証されない)です。

SQL

1select target_id 2 , max( 3 case when action_name='follow' then action_date end 4 ) as follow_date 5 , max( 6 case when action_name='favorite' then action_date end 7 ) as favorite_date 8from action_table user 9where target_type='user' and action_name in ('favorite', 'follow') -- blockは除外 10 and exists( -- いいね('favorite')をしているユーザー 11 select 1 from action_table 12 where target_id =user.target_id and action_name='favorite' 13 ) 14 and actor_id=1 15group by target_id

※2も取得する必要があるなら、exsists()の条件を外してください。

投稿2020/02/07 02:19

編集2020/02/07 11:54
sazi

総合スコア25327

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

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

ikatako

2020/02/07 11:40

あちらこちらでお世話になっております。今回もどうもありがとうございます。 1がfavoriteした相手だけを取得したいと思い where の対象を action_name='favorite' と指定したのですが、これでは follow_date が取得できず困っておりました。 その解決策が whereの対象を action_name in ('favorite', 'follow') と2つを指定しつつ、exists()を使うことなのだろうと読んだのですが、exist()の中で何が起こっているのか難しいですね。 selectの指定対象は「select カラム名」のようなカラム名だけでなく「select 1」という値でも指定できるんですね。
sazi

2020/02/07 11:50 編集

action_name in ('favorite', 'follow')はblockを除外する条件です。 action_name != 'block'でも良いですが、否定形(!=)はインデックスが使用されない事が多いので、in()で指定しています。 2はaction_name='favorite'がありません。それが除外条件なのだろうと予測して、exists()部分でその判断をしています。 existsは存在するかどうかなので別に実際の項目を必要としないのです。 select * など指定する項目は何でも良いし、値でもよいのです。 項目である必要でないなら敢えて項目は指定せず、値を指定するのが習わしのようになっています。
ikatako

2020/02/07 11:58

言われて初めて除外条件をろくに書いていないことに気づきました。除外条件はその通りです。ありがとうございます。 existsは…使い慣れるまでまだ練習が必要そうですね。いつも周辺の事情なども含めて教えてくださり感謝です。
guest

0

ちょっと仕様が理解できていないので適当ですが、SelfJoinすれば良いのでは無いでしょうか?
2,3,6行目に1行目のfollowがJoinされると思うのですが。
実際に動かしていないのでご確認ください。
二つ目のCASE文は要らないと思います。

SQL

1select favorite.target_id 2 , case when 3 follow.action_name='follow' 4 then follow.action_date else null end 5 as follow_date 6-- , case when 7-- favorite.action_name='favorite' 8-- then favorite.action_date else null end 9-- as favorite_date 10 , favorite.action_date 11 from action_table favorite 12 left outer join action_table follow on favorite.actor_id = follow.actor_id 13 and follow.action_name='follow' 14 where favorite.actor_id=1 and favorite.action_name='favorite'

投稿2020/02/06 23:35

編集2020/02/06 23:37
nandymak

総合スコア799

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

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

ikatako

2020/02/07 10:47

ありがとうございます。ご指摘のように仕様の提示が不足していたために誤解させてしまったと思います。ご回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問