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

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回答

4911閲覧

重複行を排除したビューの作成について

ariel200

総合スコア33

MySQL

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

SQL

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

0グッド

0クリップ

投稿2015/08/11 17:04

MySQLバージョン:5.6

テーブル定義
CREATE TABLE test (
id int(11) NOT NULL AUTO_INCREMENT,
user_id int(11) NOT NULL COMMENT '利用者',
input_date date NOT NULL COMMENT '入力日',
name_sei varchar(32) NOT NULL COMMENT '名前(姓)',
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

データ定義
INSERT INTO test VALUES (1,63,'2015-07-01','相沢'),(2,63,'2015-08-11','相沢'),(3,63,'2015-08-10','相沢'),(4,64,'2015-07-04','大畑'),(5,64,'2015-08-09','大畑'),(6,65,'2015-08-10','菅野'),(7,63,'2015-07-15','相沢');

SELECT結果
+----+---------+------------+----------+
| id | user_id | input_date | name_sei |
+----+---------+------------+----------+
| 1 | 63 | 2015-07-01 | 相沢 |
| 2 | 63 | 2015-08-11 | 相沢 | *
| 3 | 63 | 2015-08-10 | 相沢 |
| 4 | 64 | 2015-07-04 | 大畑 |
| 5 | 64 | 2015-08-09 | 大畑 | *
| 6 | 65 | 2015-08-10 | 菅野 | *
| 7 | 63 | 2015-07-15 | 相沢 |
+----+---------+------------+----------+

上記SELECT結果の*の行、user_idの重複を排除した上でinput_dateの最新を取得する
ビューを作成する必要があり、試行錯誤しております。
以下のクエリでビューを作ってみましたが、idが正常に取得できませんでした。

CREATE VIEW `view_test` AS select `test`.`id` AS `id`, `test`.`user_id` AS `user_id`, max(`test`.`input_date`) AS `input_date`, `test`.`name_sei` AS `name_sei` from `test` group by `test`.`user_id`

SELECT結果
+----+---------+------------+----------+
| id | user_id | input_date | name_sei |
+----+---------+------------+----------+
| 1 | 63 | 2015-08-11 | 相沢 |
| 4 | 64 | 2015-08-09 | 大畑 |
| 6 | 65 | 2015-08-10 | 菅野 |
+----+---------+------------+----------+

*の行を取得できるビューを作成する方法をご教示頂けないでしょうか?
宜しくお願い致します。

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

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

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

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

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

guest

回答2

0

ベストアンサー

他にも定番の方法としては次のような相関サブクエリを使う方法があげられます。
この方法なら user_idinput_date で重複があっても user_id ごとに1行しか返りません。
ただしたいていの場合、こっちのほうが遅いです。

sql

1CREATE VIEW `view_test` AS 2select * from test t 3where t.id = ( 4 select x.id from test x 5 where x.user_id = t.user_id 6 order by x.input_date desc, x.id desc 7 limit 1 8)

また、kokardy さんの回答と考え方はほとんど同じですが、
サブクエリを使わずに group by と having で済ませる方法もあります。
ただし、この書き方は MySQL でしかできません。
(ほか RDBMS だと group by で select にアスタリスクは使えないし group by に test の列を羅列しないといけない)

sql

1CREATE VIEW `view_test` AS 2select t.* from test t 3inner join test x on x.user_id = t.user_id 4group by t.id 5having t.input_date = max(x.input_date)

投稿2015/08/11 23:04

編集2015/08/14 05:27
ngyuki

総合スコア4514

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

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

ariel200

2015/08/12 02:39

ご回答ありがとうございました。ビューを作成し、正常に値が取得できました。 ただお恥ずかしい話ですがご提示頂いたクエリが理解できない部分が多くあります。もしよろしければ、この2つのクエリを導き出した過程をご説明頂けないでしょうか?
ngyuki

2015/08/14 05:31

グループごとのトップ1の行を取得する定番のパターンなので、、、導き出したというより、知っていたという感じです。
ariel200

2015/08/24 16:45

申し訳ありません、メール通知が来なかったためお返事に気付きませんでした。これらのクエリは定番パターンなのですね。再度のお返事ありがとうございました。
guest

0

MySQLの方言的に通るかわかりませんが、

SQL

1SELECT t.* 2FROM 3(SELECT "user_id", 4 MAX("input_date") AS max_input_date 5 FROM "test" GROUP BY "user_id") AS g 6LEFT JOIN "test" AS t 7ON t."user_id" = g."user_id" AND t."input_date" = g."max_input_date"

こういうのはいかがですか?

投稿2015/08/11 18:11

kokardy

総合スコア781

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

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

ngyuki

2015/08/11 22:59

MySQL 的には識別子のクオートはダブルクオートではなくバッククオートなのでそこだけ注意が必要です
ariel200

2015/08/12 02:35

クエリ自体は問題なく正常に値を取得できましたが、ビュー作成時に以下のエラーとなってしまいました。 ビュー作成クエリ CREATE OR REPLACE VIEW `test_view` AS SELECT t.* FROM (SELECT user_id, MAX(input_date) AS max_input_date FROM test GROUP BY user_id) AS g LEFT JOIN test AS t ON t.user_id = g.user_id AND t.input_date = g.max_input_date エラー内容 ERROR 1349: View's SELECT contains a subquery in the FROM clause MySQLではビュー作成時はFROM句にサブクエリを使用できないようです。 ですがご提示頂いたクエリは大変勉強になりました、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問