下記のテーブルから各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

回答の条件
  • URL必須
  • 1人2回まで
  • 13歳以上
  • 登録:2010/03/17 11:22:54
  • 終了:2010/03/17 16:11:40

回答(3件)

id:taknt No.1

きゃづみぃ回答回数13537ベストアンサー獲得回数11982010/03/17 11:29:09

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

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

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

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

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

id:raruken

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

2010/03/17 14:53:53
id:ko8820 No.2

ko8820回答回数1221ベストアンサー獲得回数692010/03/17 11:47:14

ポイント10pt

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

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

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

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


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

id:raruken

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

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

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

2010/03/17 14:50:31
id:Km1967 No.3

Km1967回答回数224ベストアンサー獲得回数352010/03/17 12:50:07

ポイント70pt

よくある話なのだが、グループ毎の上位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
id:raruken

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

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

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

2010/03/17 14:47:19

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません