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

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

ただいまの
回答率

91.04%

  • MySQL

    4756questions

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

MySQLでグループ毎に最新の情報を習得したい

解決済

回答 6

投稿

  • 評価 1
  • クリップ 2
  • VIEW 2,419

noripi

score 22

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

+6

nabe3さんのユーザ変数を使った方法ですが、

OracleACEのAketiJyuuzouさんとyoku0825さんと
日本オラクルの木村さんによると
MySQLのユーザ変数は評価順序が未定義だそうです。
http://qiita.com/AketiJyuuzou/items/cced9b70cc714b382d98

ゆえに、結果が保証されないと思います。

投稿

退会済みユーザー

退会済みユーザー

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • noripi

    noripi

    2016/04/01 18:14

    なるほど。勉強になります。

    キャンセル

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種類があり、よく「重い」と言われるのは相関サブクエリの方です。

投稿

編集

KiyoshiMotoki

KiyoshiMotoki

score 4627

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • noripi

    noripi

    2016/04/01 18:22

    詳しく解説していただきありがとうございます。正直サブクエリに2種類あるのはしりませんでした。勉強不足を痛感しています。
    3パターン試した結果、外部結合バージョンが一番早かったです。

    キャンセル

  • KiyoshiMotoki

    KiyoshiMotoki

    2016/04/01 18:29

    > 3パターン試した結果、外部結合バージョンが一番早かったです。
    ご丁寧な報告、ありがとうございます。

    お役に立てたなら幸いです。

    キャンセル

+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

投稿

編集

lilithchan

lilithchan

score 233

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • noripi

    noripi

    2016/04/01 18:17

    やはりサブクエリは必要ですか。

    キャンセル

+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
)

投稿

kutsulog

kutsulog

score 949

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • noripi

    noripi

    2016/04/01 18:18

    ありがとうございます。試してみます。

    キャンセル

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
と同じでは無いですか?

投稿

HiroshiWatanabe

HiroshiWatanabe

score 1679

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • nabe3

    nabe3

    2016/04/01 16:31

    price_id = 2 の期待結果が、
    price shop_id = 384, shop_id = 022, modified = 2016-03-31 13:50 ですが、
    単純な group by では、
    price shop_id = 254, shop_id = 001, modified = 2016-03-31 13:50 を返してしまうことがあります。
    group by に含まれていない price_shop_id と shop_id の値がproduct_idの
    最新のmodifiedに対する値と一致しないことがあります。

    キャンセル

  • HiroshiWatanabe

    HiroshiWatanabe

    2016/04/01 16:46

    あー…なるほど。うっかりしてました。ご指摘ありがとうございます。

    キャンセル

  • noripi

    noripi

    2016/04/01 18:13

    確かにそうですね。

    キャンセル

-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;

投稿

nabe3

nabe3

score 295

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • noripi

    noripi

    2016/04/01 18:15

    このような書き方もあるのですね。

    キャンセル

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

ただいまの回答率

91.04%

関連した質問

同じタグがついた質問を見る

  • MySQL

    4756questions

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

SNSアカウントでログイン

  • Facebookでログイン
  • Twitterでログイン
  • Googleでログイン
  • Githubでログイン
  • Hatenaでログイン

teratailアカウントでログイン

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る