MySQLでグループ毎に最新の情報を習得したい
解決済
回答 6
投稿
- 評価 1
- クリップ 2
- VIEW 2,419
MySQL5.5で下記の商品データベースから、各商品ID毎の最新情報を取得したいです。
《product》
| product_id | price shop_id | shop_id | modified |
| 1 | 100 | 001 | 2016-03-30 14:00|
| 1 | 148 | 015 | 2016-03-30 15:00|
| 2 | 254 | 001 | 2016-02-26 14:31|
| 2 | 384 | 022 | 2016-03-31 13:50|
| 2 | 482 | 016 | 2016-01-24 10:00|
| 3 | 851 | 015 | 2016-03-30 14:00|
| 3 | 650 | 022 | 2016-03-14 16:00|
| 3 | 500 | 016 | 2016-03-26 14:30|
《結果》
| product_id | price shop_id | shop_id | modified |
| 1 | 148 | 015 | 2016-03-30 15:00|
| 2 | 384 | 022 | 2016-03-31 13:50|
| 3 | 851 | 015 | 2016-03-30 14:00|
また、実際のDBには大量に情報があるため、できるだけ軽い処理にしたいです。
処理時間のかかるサブクエリは避けたいです。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+6
nabe3さんのユーザ変数を使った方法ですが、
OracleACEのAketiJyuuzouさんとyoku0825さんと
日本オラクルの木村さんによると
MySQLのユーザ変数は評価順序が未定義だそうです。
http://qiita.com/AketiJyuuzou/items/cced9b70cc714b382d98
ゆえに、結果が保証されないと思います。
投稿
退会済みユーザー
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
checkベストアンサー
+4
以下のページが、まさに同じ問題に対する解決策を提示してくれています。
https://dev.mysql.com/doc/refman/5.6/ja/example-maximum-column-group-row.html
ご質問のテーブル構造に当てはめると、以下のようになるかと思います。
■相関サブクエリ バージョン
SELECT main.* FROM product AS main WHERE modified = (
SELECT MAX(modified) FROM product AS sub WHERE main.product_id = sub.product_id
);
■非相関サブクエリ バージョン
SELECT main.* FROM product AS main
INNER JOIN (
SELECT product_id, MAX(modified) AS modified FROM product GROUP BY product_id
) AS sub
ON main.product_id = sub.product_id AND main.modified = sub.modified;
■外部結合バージョン
SELECT main.* FROM product AS main
LEFT OUTER JOIN product AS sub ON main.product_id = sub.product_id AND main.modified < sub.modified
WHERE sub.modified IS NULL;
ただし、
できるだけ軽い処理にしたいです。
処理時間のかかるサブクエリは避けたいです。
について、クエリの実行時間はインデックスの有無やデータの分布具合によっても変わるため、一概にサブクエリが重いとは限りません。
実装しようとしているクエリの性能を確認したければ、実際にテストデータを投入したDBに流してみるのと、実行計画を確認するのがよいです。
実行計画については、以下のサイトが参考になります。
https://dev.mysql.com/doc/refman/5.6/ja/explain.html
http://nippondanji.blogspot.jp/2009/03/mysqlexplain.html
ちなみに、サブクエリにも相関サブクエリと非相関サブクエリの2種類があり、よく「重い」と言われるのは相関サブクエリの方です。
投稿
score 4627
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+2
サブクエリ必要な気がします。
最初に各商品IDの最新日付を取得してからJOINと言う形が一般的ですね。
SELECT p.product_id, p.price, p.shop_id, p.modified FROM product p
INNER JOIN (
SELECT product_id, MAX(modified) modified
FROM product
GROUP BY product_id
) max_p
ON p.product_id = max_p.product_id
AND p.modified = max_p.modified
投稿
score 233
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+2
JOINかEXISTSを使うべきかと
JOIN
SELECT
A.*
FROM product A
JOIN (
SELECT
B.product_id
, MAX(modified) modified
FROM product B
GROUP BY
B.product_id
) C
ON C.product_id = A.product_id
AND C.modified = A.modified
EXISTS
SELECT
*
FROM procudt A
WHERE NOT EXISTS(
SELECT 1
FROM product B
WHERE B.product_id = A.product_id
AND B.modified > A.modified
)
投稿
score 949
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
group by と max ですかね
select product_id, price_shop_id, shop_id, MAX(modified) as modified from product group by product_id;
な感じ?
この問題はもしかして
https://teratail.com/questions/31016
と同じでは無いですか?
投稿
score 1679
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
-4
こちらのSQLではいかがでしょうか?
product_idごとにmodifiedの新しいもの順に1, 2, 3とナンバリングし、
No1のレコードのみを抽出します。
SELECT t.product_id, t.price_shop_id, t.shop_id, t.modified
FROM
(
SELECT @row_num := IF(@prev_value=p.product_id,@row_num+1,1) AS RowNumber,
p.product_id,
p.price_shop_id,
p.shop_id,
p.modified,
@prev_value := p.product_id
FROM product p,
(SELECT @row_num := 1) x,
(SELECT @prev_value := 'x') y
ORDER BY p.product_id, p.modified DESC
) t
WHERE t.RowNumber = 1
ORDER BY product_id;
投稿
score 295
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
91.04%
noripi
2016/04/01 18:14