人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

下記のテーブルから各IDごとの最新2件のデータを一回のSQLで抽出したいのですが
UNIONを使えばできました。
UNIONは実行結果をひとつにまとめてるだけなので結局2回SQLを実行していますよね?
UNIONを使わずに1回の実行で抽出は可能でしょうか。
またもっとスマートな抽出方法がありましたら教えてください。


元テーブル:TABLE_A
ID|Address | create_date
1 | 東京 | 2010-03-01
2 | 福岡 | 2010-03-02
1 | 東京 | 2010-03-03
1 | 東京 | 2010-03-04
2 | 福岡 | 2010-02-05
1 | 東京 | 2010-03-06
1 | 東京 | 2010-03-07
2 | 福岡 | 2010-03-08
1 | 東京 | 2010-03-09
1 | 東京 | 2010-03-10
2 | 福岡 | 2010-03-11
1 | 東京 | 2010-03-12



抽出したい実行結果
ID|Address | create_date
1 | 東京 | 2010-03-12
1 | 東京 | 2010-03-10
2 | 福岡 | 2010-03-11
2 | 福岡 | 2010-09-08

●質問者: raruken
●カテゴリ:コンピュータ ウェブ制作
✍キーワード:2010-02-05 2010-03-01 2010-03-03 2010-03-08 2010-03-10
○ 状態 :終了
└ 回答数 : 3/3件

▽最新の回答へ

1 ● きゃづみぃ
●0ポイント

http://www.geocities.jp/mickindex/database/db_optimize.html

http://www.accessclub.jp/sql/19.html

inを使えば 同様になります。

Address in("東京","福岡" )

記述の仕方は データベースによって違う場合があります。

◎質問者からの返答

少し求めていた回答と違う気が・・・・でもありがとうございま。


2 ● ko8820
●10ポイント

>UNIONは実行結果をひとつにまとめてるだけなので結局2回SQLを実行していますよね?

副問い合わせとか使うより、断然検索が速いですよ。

実際には、SQLの実行計画を取得して、実際に実行してる構文を見るべきですね。

1つのSQLでも、複数の工程で検索されます。


http://www.atmarkit.co.jp/fdb/rensai/orasql05/orasql05_4.html

◎質問者からの返答

おっしゃるとおりだと思います。

EXPLAINはほとんど使ったことなかったのですがこれを機会に試してみます。

ありがとうございました。


3 ● Km1967
●70ポイント

よくある話なのだが、グループ毎の上位n位を一発で抽出する方法はない。 だがUNIONで2回よりは下のような方法を用いるほうがメモリ節約・時間節約だ。

手前味噌の過去回答だが速度差は歴然。

http://q.hatena.ne.jp/1268119392#c174023


対処方法はRDBMS毎に違うから、次回からはRDBMSが何かを明記してくれたまえ。


データ(インデックスすらも省略の手抜き)

CREATE TEMPORARY TABLE TABLE_A (ID INT, Address TEXT, create_date DATE);
INSERT INTO TABLE_A VALUES
(1,'東京','2010-03-01'),
(2,'福岡','2010-03-02'),
(1,'東京','2010-03-03'),
(1,'東京','2010-03-04'),
(2,'福岡','2010-02-05'),
(1,'東京','2010-03-06'),
(1,'東京','2010-03-07'),
(2,'福岡','2010-03-08'),
(1,'東京','2010-03-09'),
(1,'東京','2010-03-10'),
(2,'福岡','2010-03-11'),
(1,'東京','2010-03-12');

MySQL の例。

SET @id = '', @c = 0;
SELECT ID, Address, create_date
FROM (
 SELECT *
 , IF(@id <> ID, @c := 1, @c := @c + 1) c
 , IF(@id <> ID, @id := ID, @id := @id) i
 FROM TABLE_A
 ORDER BY ID, create_date DESC
) a
WHERE c <= 2;

PostgreSQLやORACLEなどの例

SELECT ID, Address, create_date
FROM (
 SELECT *, rank() OVER (PARTITION BY ID ORDER BY ID, create_date, DESC) r
 FROM TABLE_A
) a
WHERE r <= 2
◎質問者からの返答

RDBMSの記述を忘れてしまい申し訳ありませんでした。mysqlです。

おかげさまで無事実装できました。

とても参考になりました、ありがとうございます。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ