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

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

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

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

Q&A

解決済

2回答

284閲覧

直前の情報を合せて取得したい(クエリ)

tkda

総合スコア23

MySQL

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

0グッド

0クリップ

投稿2017/10/02 02:55

編集2017/10/02 04:17

現在、下記のテーブルのように、日々の商品の状態をitem_statusテーブルで保存しています。

lang

1CREATE TABALE `items(商品)` ( 2 `id` int(11) NOT NULL AUTO_INCREMENT, 3 `name` varchar(16) NOT NULL, 4 PRIMARY KEY (`id`), 5); 6 7CREATE TABALE `status(状態)` ( 8 `id` int(11) NOT NULL AUTO_INCREMENT, 9 `name` varchar(16) NOT NULL, 10 PRIMARY KEY (`id`), 11); 12 13CREATE TABALE `items_status` ( 14 `id` int(11) NOT NULL AUTO_INCREMENT, 15 `item_id` int(1) NOT NULL, 16 `status_id` int(2) NOT NULL, 17 `output_date` date NOT NULL, 18 PRIMARY KEY (`id`), 19);

今回、例えばoutput_dateが今日のものを全件取得する際に、直前のstatusを合せて取得したいと考えております。

ただし、単純に昨日のstatusを取得するというものではなく、今日のstatusと異なる、もっとも直近のstatusを直前のstatusと定義しております(存在しない場合はNULL)。

追記:
サンプルデータと取得したい情報は以下のとおりです。

###items(商品)

idname
1サーモン
2昆布

###status(状態)

idname
1good
2poor
3bad

###items_status

iditem_idstatus_idoutput_date
1112017-09-01
2212017-09-01
3122017-09-02
4212017-09-02
5132017-09-03
6212017-09-03
7132017-09-04
8212017-09-04

###取得したい情報(output_date: 2017-09-04を指定)
|items.name|status.name|status.name(直前)|output_date|
|:--|:--|:--|
|サーモン|bad|poor|2017-09-04|
|昆布|good|NULL|2017-09-04|

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

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

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

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

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

yambejp

2017/10/02 03:09

具体的なsampleデータをつけて、どういった結果をほしいか提示下さい。いまのテーブル構成ですと、status_idがユニークでなく、id毎のoutput_dateもユニークではありません。そうなると別のなんらかの条件がない場合直前のstatus_idをユニークに抜き出すことは理論上できません
tkda

2017/10/02 04:18

ご指摘ありがとうございます。できるだけシンプルにと思って記載したつもりがまったく情報が足りておりませんでした。一から質問内容を書き直しております。
guest

回答2

0

ベストアンサー

itemsを駆動表として、「指定日付のstatusと異なる、過去直近の日付を求めたitems_status」とitems_statusをそれぞれ、item_idと求めた日付で結合

SQL

1select itm.name 2 ,(select name from status where id=sts.status_id) 3 ,(select name from status where id=lag_sts.status_id) 4 , sts.output_date 5from items as itm 6 left join ( 7 select * 8 ,(select max(output_date) from items_status 9 where item_id=st.item_id 10 and output_date < st.output_date 11 and status_id <> st.status_id 12 ) as lag_output_date 13 from items_status as st 14 where output_date='2017-09-14' 15 ) sts 16 on itm.id=sts.item_id 17 left join items_status as lag_sts 18 on sts.item_id=lag_sts.item_id 19 and sts.lag_output_date=lag_sts.output_date

※状態名はサブクエリーにしていますが、joinして取得の方が高速かもしれません。

投稿2017/10/03 15:49

編集2017/10/04 02:37
sazi

総合スコア25173

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

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

tkda

2017/10/04 01:25

ありがとうございます。無事に私の環境でも再現ができました!
guest

0

items_statusのitem_id、output_dateはuniqueではないのでしょうか?
仮にitems_statusが以下のようなデータだったとき

SQL

1CREATE TABLE `items_status` ( 2 `id` int(11) NOT NULL AUTO_INCREMENT, 3 `item_id` int(1) NOT NULL, 4 `status_id` int(2) NOT NULL, 5 `output_date` date NOT NULL, 6 PRIMARY KEY (`id`), 7 UNIQUE(item_id,output_date) 8); 9 10insert into items_status values 11(1,1,1,'2017-09-01'), 12(2,2,1,'2017-09-01'), 13(3,1,2,'2017-09-02'), 14(4,2,1,'2017-09-02'), 15(5,1,3,'2017-09-03'), 16(6,2,1,'2017-09-03'), 17(7,1,3,'2017-09-04'), 18(8,2,1,'2017-09-04'), 19(9,3,1,'2017-09-04'); 20

考え方

抽出するデータは’2017-09-04'をベースに
id=1は2017-09-03のstatus_id=3なのでNG、遡って2017-09-02のstatus_id=2
id=2は遡ってもstatus_id=1以外のデータがないのでnull
id=3は遡ってもそもそもデータがないのでnull

という計算根拠ですね?

投稿2017/10/02 07:35

yambejp

総合スコア114784

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

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

tkda

2017/10/02 07:51

確かに、item_id, output_dateはuniqueですね。 また、計算根拠につきましても「考え方」に記載の通りで間違いありません。 たびたびのご指摘ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問