🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
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回答

6693閲覧

同じテーブルの違う条件で一件だけ取得したレコードを取得したい

tk68716

総合スコア24

MySQL

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

SQL

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

0グッド

0クリップ

投稿2021/02/11 09:10

編集2021/02/11 10:03

使用DBサーバ MySQL
バージョン 5.6

同一テーブルから、複数の条件で一件ずつ取得したレコードをUNIONしたいのですが方法がわかりません。
例として下のようなテーブルがあるとします。

テーブル名 emp_data

idステータス行き先登録日
1Cテスト公園2021/01/30
2Bテストビル2021/02/01
3Aテスト公園2021/02/02
4Aテスト病院2021/02/03
5Cテスト病院2021/02/04
6Aテストビル2021/02/05
7Bテスト公園2021/02/06
8Aテスト公園2021/02/07
9Cテストビル2021/02/08
10Aテスト病院2021/02/09

ステータスがそれぞれA、B、Cとあり、それぞれのステータスで一件だけ取得したレコードをUNION ALLするもうまくできません。
問題のコード

SQL

1SELECT * 2FROM emp_data 3WHERE ステータス='A' 4ORDER BY 登録日 DESC 5LIMIT 1 6UNION ALL 7SELECT * 8FROM emp_data 9WHERE ステータス='B' 10ORDER BY 登録日 DESC 11LIMIT 1 12UNION ALL 13SELECT * 14FROM emp_data 15WHERE ステータス='C' 16ORDER BY 登録日 DESC 17LIMIT 1

取得したい結果

idステータス行き先登録日
10Aテスト病院2021/02/09
7Bテスト公園2021/02/06
9Cテストビル2021/02/08

どのようにSQLを組めばよいでしょうか。
お力添えよろしくお願いします。

テーブル定義書
![イメージ説明

回答者様用SQL
こちらのSQLを流していただくと私の環境と同じ環境が出来上がると思います

SQL

1/* DB作成*/ 2create database test 3 4/* ユーザー作成*/ 5grant all on blog_cakephp.* to test@localhost identified by 'test'; 6use test 7 8/* テーブル作成 */ 9create emp_data ( 10 id int unsigned auto_increment primary key, 11 status char(1), 12 destination varchar(255), 13 created datetime default null, 14); 15 16insert into posts (status, destination, created) values 17('A', 'テスト公園', now()), 18('B', 'テスト公園', now()), 19('C', 'テスト公園', now()), 20('A', 'テスト病院', now()), 21('B', 'テスト病院', now()), 22('C', 'テスト病院', now()), 23('A', 'テスト歯医者', now()), 24('B', 'テスト歯医者', now()), 25('C', 'テスト歯医者', now());

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

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

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

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

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

m.ts10806

2021/02/11 09:19

>使用DBサーバ MySQL 質問タグに「MySQL」を追加 バージョンを質問本文に記載してください。 あと、テーブル定義とサンプルデータをCREATE TABLE文、INSERT文で提示してください。
tk68716

2021/02/11 10:06

質問文追記させていただきました。よろしくお願いします。
YT0014

2021/02/11 12:31

試されたSQLのカラム名とテーブル定義のカラム名が異なります。 また、作成用SQLですが、セミコロンの漏れや余分な行末のカンマなど、実行が不可能なものです。また、作成されるレコードも、ご提示いただいたものとは異なります。 ご提示いただく前に、ご自身の環境での確認をお願いいたします。
YT0014

2021/02/11 12:43

登録日(created)が同一になる可能性はあるのでしょうか? 同一が許容される場合、どのレコードが選択されても構わないのでしょうか?
tk68716

2021/02/14 04:21

提示しているテーブルはあくまで例なので、、、 すみません確認不足でした。
guest

回答2

0

ステータスがそれぞれA、B、Cとあり、それぞれのステータスで一件だけ取得したレコードをUNION ALLする

これは実際には「同じステータスのデータで、もっとも登録日(created)が新しいものが欲しい」ということでしょうか? であれば、MySQL5.7では以下のようなSQLになりそうです。

SQL

1SELECT * 2FROM emp_data AS a 3WHERE NOT EXISTS ( 4 SELECT * 5 FROM emp_data AS b 6 WHERE a.status = b.status 7 AND a.created < b.created 8);

MySQL8.0以降ではウィンドウ関数がサポートされたので、RANK()関数を使って実現することが多いと思います。

SQL

1SELECT * 2FROM ( 3 SELECT 4 *, 5 RANK() OVER (PARTITION BY status ORDER BY created DESC) AS RNK 6 FROM emp_data 7) AS a 8WHERE RNK = 1;

投稿2021/02/12 09:39

neko_the_shadow

総合スコア2349

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

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

tk68716

2021/02/14 04:19

ご回答ありがとうございます。
guest

0

ベストアンサー

各々のSELECT文を、カッコ()で囲めば、ご希望の結果になります。
なお、以下のSQLは、ご提示いただいた作成用SQLのカラム名を用いています。

MySQL

1(SELECT * 2FROM emp_data 3WHERE status='A' 4ORDER BY created DESC 5LIMIT 1) 6UNION ALL 7(SELECT * 8FROM emp_data 9WHERE status='B' 10ORDER BY created DESC 11LIMIT 1) 12UNION ALL 13(SELECT * 14FROM emp_data 15WHERE status='C' 16ORDER BY created DESC 17LIMIT 1);

登録日/createdが、ステータス/status毎にユニークであることが保証されるなら、以下のSQLのほうが、ステータスの増加にも対応できるので、お勧めですが。

MySQL

1SELECT * FROM emp_data 2 WHERE (status , created) IN 3 (SELECT status , max(created) FROM emp_data GROUP BY status) 4 ORDER BY status;

投稿2021/02/11 12:54

YT0014

総合スコア1748

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

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

tk68716

2021/02/14 04:19

ご回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問