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

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

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

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

SQL

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

Q&A

解決済

2回答

3939閲覧

SELECT文で用いた列をHAVING句でももう一回使用する方法

trafalbad

総合スコア303

MySQL

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

SQL

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

0グッド

1クリップ

投稿2018/01/15 13:31

編集2018/01/16 07:45

次のコードのようにSELECT文でuser_masterテーブルのinstall_datetimeを選択します。
この後のGYOUP BY句およびHAVING句で以下の条件を満たすようにします
①login_logテーブルで各ユーザー毎にinstall_datetimeから三日以内に3つ以上のuser_idが表示されているuser_idをGROUP_BYに指定する

SQL

1SELECT install_datetime AS days, user_id 2FROM user_master 3WHERE delete_flg=0 AND days LIKE '3%' 4GROUP BY user_id 5HAVING user_id IN(SELECT user_id 6 FROM login_log 7 WHERE COUNT(user_id)>=3 AND timestamp BETWEEN days AND DATEADD(day, 3, days));

この時条件①を満たすコードとしてuser_masterテーブルのinstall_datetimeをHAVING句で再び使用して見たのですが、うまく行きません。
条件①を満たすために何か良い手法はないかご教授いただけないでしょうか?

またテーブルは以下のように作成しました

SQL

1CREATE TABLE user_master 2(user_id INTEGER, 3 install_datetime CHAR(13), 4 delete_flg INTEGER); 5 6INSERT INTO user_master VALUES (10001, '3/19/16 15:45', 0), 7 (10002, '3/21/16 12:30', 1), 8 (10003, '3/23/16 9:15', 0), 9 (10004, '3/25/16 6:00', 0), 10 (10005, '3/19/16 15:45', 1); 11 12 13CREATE TABLE login_log 14(user_id INTEGER, 15 timestamp CHAR(18)); 16 17INSERT INTO login_log VALUES (10001, '3/19/16 15:50'), 18 (10001, '3/20/16 0:20'), 19 (10001, '3/23/16 14:10'), 20 (10001, '3/24/16 0:15'), 21 (10002, '3/21/16 12:50'), 22 (10003, '3/23/16 11:00'), 23 (10003, '3/24/16 9:10'), 24 (10003, '3/24/16 11:20'); 25

追記
テーブルは与えられているもので、データ型や内容等は変更できないものとして、テーブルの内容を変更せずに条件を満たすことを考えてます。

解決方法メモ
条件
delete_flg=0
install_datetime LIKE '4%
timestampがinstalldatetimeから3日以内の範囲であること
login_logのuser_idが3回以上表示されていること

手順1.条件を分解、各条件を満たすために順に割り当てていく
手順2.GROUP BY句でグループ分けするものを決める、他はWHERE句で指定

SQL

1SELECT L.user_id, U.install_datetime , COUNT(L.user_id) 2FROM login_log AS L INNER JOIN user_master AS U 3ON L.user_id=U.user_id 4WHERE STR_TO_DATE(L.timestamp,'%m/%d/%y %H:%i') BETWEEN STR_TO_DATE(U.install_datetime,'%m/%d/%y %H:%i') and STR_TO_DATE(U.install_datetime,'%m/%d/%y %H:%i') + interval 3 day AND 5U.delete_flg=0 AND U.install_datetime LIKE '4%' 6GROUP BY L.user_id 7HAVING COUNT(*)>=3

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

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

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

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

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

guest

回答2

0

havingだとgroup by 項目でなければ指定できないので、where条件にすれば良いと思いますけど。
※サブクエリー内でhaving

SQL

1SELECT user_id 2FROM user_master 3WHERE delete_flg=0 AND install_datetime LIKE '3%' 4 and user_id IN( 5 SELECT user_id FROM login_log 6 WHERE timestamp BETWEEN days AND DATEADD(day, 3, days) 7 group by user_id 8 having COUNT(user_id)>=3 9 ) 10GROUP BY user_id 11;

投稿2018/01/15 13:46

sazi

総合スコア25173

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

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

0

ベストアンサー

日付を文字列型でもつのは効率がわるいと思います

SQL

1CREATE TABLE user_master(user_id INTEGER,install_datetime datetime,delete_flg tinyint not null); 2 3INSERT INTO user_master VALUES 4(10001,'2016-03-19 15:45',0), 5(10002,'2016-03-21 12:30',1), 6(10003,'2016-03-23 09:15',0), 7(10004,'2016-03-25 06:00',0), 8(10005,'2016-03-19 15:45',1); 9 10CREATE TABLE login_log(user_id INTEGER,timestamp datetime); 11 12INSERT INTO login_log VALUES 13(10001,'2016-03-19 15:50'), 14(10001,'2016-03-20 00:20'), 15(10001,'2016-03-23 14:10'), 16(10001,'2016-03-24 00:15'), 17(10002,'2016-03-21 12:50'), 18(10003,'2016-05-23 11:00'), 19(10003,'2016-05-24 09:10'), 20

ここで、install_datetimeから3日以内のものを集約すると

SQL

1select t1.user_id,count(*) from login_log as t1 2inner join user_master as t2 on t1.user_id=t2.user_id 3where t1.timestamp between t2.install_datetime and t2.install_datetime + interval 3 day 4group by t1.user_id;

結果

user_idcount(*)
100012
100021

よって、3つ以上のものは存在しませんが大丈夫でしょうか?

SQL

1select t1.user_id 2from login_log as t1 3inner join user_master as t2 on t1.user_id=t2.user_id 4where t1.timestamp between t2.install_datetime and t2.install_datetime + interval 3 day 5group by t1.user_id 6having count(*)>=3

※値なし

キャストしながら処理

SQL

1select t1.user_id,count(*) from login_log as t1 2inner join user_master as t2 on t1.user_id=t2.user_id 3where str_to_date(timestamp,'%m/%d/%y %H:%i') between str_to_date(install_datetime,'%m/%d/%y %H:%i') and str_to_date(install_datetime,'%m/%d/%y %H:%i') + interval 3 day 4group by t1.user_id

SQL

1select t1.user_id from login_log as t1 2inner join user_master as t2 on t1.user_id=t2.user_id 3where str_to_date(timestamp,'%m/%d/%y %H:%i') between str_to_date(install_datetime,'%m/%d/%y %H:%i') and str_to_date(install_datetime,'%m/%d/%y %H:%i') + interval 3 day 4group by t1.user_id 5having count(*)>=3

投稿2018/01/15 14:04

編集2018/01/15 14:42
yambejp

総合スコア114769

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

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

trafalbad

2018/01/15 14:13 編集

テーブルの内容は変更できないものとして求めたいのですが解決策ご教授いただけないでしょうか?
trafalbad

2018/01/16 07:45

解決しました、ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問