- PR -

DISTINCに関しての質問

投稿者投稿内容
ぬべたそ
ベテラン
会議室デビュー日: 2003/12/18
投稿数: 72
投稿日時: 2007-06-07 18:14
ある業務Aの登録内容を履歴で保存しているテーブルがあります。
テーブル構造は以下のようになっています。

テーブルA
DATA_ID(PK):業務Aの操作対象となったデータを識別する番号
REVISION(PK):あるデータに対して業務Aを行った回数
TOROKU_DATE:業務Aを行った日次

つまり、あるデータ(DATA_ID=1)に対して業務Aを行った場合、
1,1,2007/5/4
と登録され、もう一度同じデータに対して業務Aを行った場合は、
1,2,2007/5/5
のように登録されます。

この時、各データに対して業務Aを最後に行ったレコードを取得したい(回数も取得したい)場合、どのようにすればよろしいでしょうか?
SELECT DISTINCT DATA_ID,REVISION,DATE FROM テーブルA
ORDER BY ID,REVISION
とすると、DISTINCTが効かず、履歴の数だけヒットしてしまいます。

また、現在は副問合せを用いているのですが、パフォーマンスが悪いため方法を模索しているところです。

以上、宜しくお願い致します。
末記入
常連さん
会議室デビュー日: 2006/09/05
投稿数: 23
投稿日時: 2007-06-07 18:35
select DATA_ID, max(REVISION) as REVISION, max(TOROKU_DATE) as TOROKU_DATE
from テーブルA
group by DATA_ID
ぬべたそ
ベテラン
会議室デビュー日: 2003/12/18
投稿数: 72
投稿日時: 2007-06-08 08:30
返信ありがとうございます。
説明が足りていないようでした。申し訳ありません。

例えばテーブルAに次のようなレコードが登録済みだとします。
最初の説明にカラムを一つ追加させて頂きました。

DATA_ID | REVISION | TOROKU_DATE | CONTENTS
1 | 1 | 2007/5/4 | 登録
1 | 2 | 2007/5/5 | 修正
2 | 1 | 2007/5/6 | 登録

この時に、それぞれのデータに関して、最新の業務内容のレコードを抜き出したいのです。

DATA_ID | REVISION | TOROKU_DATE | CONTENTS
1 | 2 | 2007/5/5 | 修正
2 | 1 | 2007/5/6 | 登録

現在は、
SELECT DATA_ID,REVISION,TOROKU_DATE,CONTENTS
FROM テーブルA
WHERE REVISION = (
SELECT MAX(B.REVISION) FROM テーブルA B
WHERE B.ID=テーブルA.ID)
のように副問合せを使って実現しているのですが、レコード数が増加し他のテーブルと結合する場合にパフォーマンスを落としているようなので、他の方法を模索しています。

どうぞ宜しくお願い致します。

めだか
大ベテラン
会議室デビュー日: 2004/11/11
投稿数: 109
投稿日時: 2007-06-08 10:47
Existsを使う
ID,REVISIONにインデックスを付ける
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2007-06-08 11:14
開発環境(DB等)が書かれてないから、できるかどうかは分からないけど、
derived table(inline view)を使ってみるとか。

例:
コード:
SELECT
    V.DATA_ID, V.REVISION, A.TOROKU_DATE, A.CONTENTS
FROM 
    テーブル A
JOIN (SELECT
        A1.DATA_ID, MAX(A1.REVISION) AS REVISION
    FROM
        テーブルA A1
    GROUP BY
        A1.DATA_ID
) V
    ON A.DATA_ID = V.DATA_ID
    AND A.REVISION = V.REVISION



適当に作ったから、できるかどうかは知らん。

ぬべたそ
ベテラン
会議室デビュー日: 2003/12/18
投稿数: 72
投稿日時: 2007-06-08 14:35
めだかさん、かずくんさん、ご返信ありがとうございます。

>めだかさん
Existsを使うとは具体的にはどのような方法でしょうか?
DATA_ID,REVISIONは二つでプライマリキーであるため、二つ合わせたインデックスは既に存在していますが、別々にインデックスを追加することでパフォーマンスがアップするということですか?

>かずくさん
環境はOracleです。
書いていただいたコードを作成しExplainで確認してみましたが、元々の副問合せを利用したものとCOSTが同じ値でした。
めだか
大ベテラン
会議室デビュー日: 2004/11/11
投稿数: 109
投稿日時: 2007-06-08 14:47
こんな感じ
動くかどうか不明です

SELECT DATA_ID,REVISION,TOROKU_DATE,CONTENTS
FROM テーブルA
WHERE exists (
SELECT * FROM テーブルA B
WHERE B.ID=テーブルA.ID group by DATA_ID having max(b.revision) = テーブルA.revision )

>インデックスは既に存在していますが
でしたら不要だと思われます

かずくんさんのインラインビューの方が速そう
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2007-06-08 15:07
引用:

ぬべたそさんの書き込み (2007-06-08 14:35) より:

環境はOracleです。


今後、スレ立てて質問するときは、バージョンも書こうね。

引用:

書いていただいたコードを作成しExplainで確認してみましたが、元々の副問合せを利用したものとCOSTが同じ値でした。


インデックスのチューニングで解決するかもしれないので、その実行計画(EXPLAIN)の出力結果も提示してください。

スキルアップ/キャリアアップ(JOB@IT)