2009-06-09 2 views
3

これは私が持っているデータのサンプルです。サブクエリを使用しない高度なグループ化

-ID-  -Rank-  -Type-  -Status- -Amount- 
1142474  2  Under Offer Approved 23 
1148492  1  Present  Current  56 
1148492  2  Under Offer Approved 3 
2273605  1  Present  Current  24 

ここで、IDは同じですが、私は最も高いランクのレコードのみが必要です。したがって、クエリの最終結果。元のデータセットを取得する

-ID-  -Rank-  -Type-  -Status- -Amount- 
1142474  2  Under Offer Approved 23 
1148492  1  Present  Current  56 
2273605  1  Present  Current  24 

は高価な操作ですので、私はは IDでグループを行う、その後分ランクにしたくない当時合流を再度データセットに追加します。したがって、クエリは別の方法でその作業を行う必要があります。

乾杯 アンソニー一般的に利用可能

答えて

1
select t1.id 
     , t1.rank 
     , t1.type 
     , t1.status 
     , t1.amount 

from my_table t1 

     left outer join my_table as t2 
     on t1.id = t2.id 
    and 
     t2.rank < t1.rank 

where t2.id is null 
+0

この場合、t2には何がありますか? –

+0

@Anthony:t2への結合は、自己結合とも呼ばれます。それは同じテーブルの別のコピーです。その理由は、述語(結合条件とWHERE句)で、各IDの上位ランクの項目以外のすべてを除外したいということです。 – bernie

+0

@adam:問題は、my_tableからデータを取得するのが非常に高価(つまり2〜6秒)なので、テーブルに再び参加することを避けたいということです。 –

0

のオプションが含まれます:

  • ストア一時表に示したデータは、一時テーブルを照会。
  • 複雑なクエリを定義するのにWITH句を使用し、DBMSにクエリを並べ替えるようにします。

WITH句を使用すると、サブクエリに名前を付けることができます。可能であれば、オプティマイザは再評価を回避します。 TEMPテーブルの解決策は最も簡単です。そしてそれはIDとMIN(ランク)のGROUP BYを行い、再び参加します。

2
SELECT * FROM TheTable 
WHERE 1 = ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Rank DESC) 
+0

これは私の最初の本能でした。おそらく、OPはいくつかのタイミング結果を発表するだろう。 – bernie

+0

私の状況では、レコードのために、このケースではエラーが発生します - 「ウィンドウ関数はSELECT句またはORDER BY句にしか現れません。だから私は、サブクエリと外側のクエリのどこの部分に上の部分を配置する必要がありました。 –

6

これは動作します:

with temp as (
select *, row_number() over (partition by id order by rank) as rownum 
from table_name 
) 
select * from temp where rownum = 1 

はとても高価なデータセットを取得しているなぜ、私はひどく何も見えませんランクは少なくとも数

0

を表し、IDごとに一つのレコードを与えますここでは複雑です。あなたは必要なインデックスを持っていますか、それを使っているクエリですか?統計は古くなっていますか?

+0

質問のために、私はシナリオを単純化しました。基本的に表は、Table_valued関数です。これは、2つの他のTable_valued関数からの結果です。各関数は、約6つの一時表を使用して結果を構築します。これは、データベースに存在する正規化のレベルと、データの画像を構築するために必要なデータの量に起因します。実際には、このデータはマテリアライズド・ビューなどでキャプチャする必要があります。しかし、私はこのような変更をこのリリースサイクルで行うことはできません。乾杯 –

関連する問題