2011-02-02 16 views
0

私はSQLについて簡単な質問(?)を持っています。私は数回前にこの問題に遭遇しましたが、私はいつもそれを解決しましたが、私はより洗練されたソリューションとおそらくより速いソリューションを探しています。タイムスタンプに基づいて1つの行を除いて、すべての結果を取得するにはどうすればよいですか?

問題は、タイムスタンプ値の最大値を持つテーブル以外のすべての行を選択することです(この場合はサマリー行ですが、これはどのような方法でもマークされていないため、私の結果に関連する)。

私はこのような何か行うことができます:

select * from [table] t 
where loggedat < (select max(loggedat) from [table] and somecolumn='somevalue') 
and somecolumn='somevalue' 

をしかし、大きなテーブルで作業する場合、これは一種の遅いようです。助言がありますか?

+0

SQLサーバー、Oracle、「アクセス」?どのデータベースを使用していますか? – riffnl

+0

あなたのソリューションは私には完全に(そしてエレガントに)見えます。結合が速くなる(または遅くなる)ことがあります。 –

+0

これはMS SQL Server(2005)です。 – cuj74

答えて

0

使用すると、1つ小さな(4バイト)余分な列を気にしないだけであれば、あなたは、おそらくこのように行くかもしれない:あなたは余分な列を気に行う場合

SELECT * 
FROM (
    SELECT *, ROW_NUMBER() OVER (ORDER BY loggedat DESC) AS rownum 
    FROM [table] t 
    WHERE somecolumn = 'somevalue' 
    /* and all the other filters you want */ 
) s 
WHERE rownum > 1 

を、あなたがするだけでしょう必要な列を外部SELECTに明示的にリストします。

+0

ありがとう、これは動作し、それは他より速いようです。少なくともテーブルスキャンは少なくて済む:-) – cuj74

+0

フィルタを繰り返す必要がないので、私はそれを考えました。もう1つのメリットは、フィルタを繰り返す必要がないことです。 :) –

1

DB構造を変更したくない場合は、クエリ(または<の代わりに<>を使用してわずかなバリエーションを持つもの)を使用してください。

テーブルに列IsSummary bitを追加して、常に最新の行をtrue(それ以外はすべてfalse)としてマークすることができます。 (挿入もIsSummary値の更新をトリガーするので)これは、SELECTクエリの高速化と引き換えにインサート上で遅い速度を犠牲になり

Select * from [table] where IsSummary = 0 and somecolumn = 'somevalue' 

:次に、あなたのクエリに変わります。

+0

ねえ、あなたはその場を打つ。下にある問題は、除外したい行が要約としてマークされておらず、残念ながら私はそれを変更できないということです。 – cuj74

+0

次に、1つのクエリでそれを実行したい場合は、それ以外のことはあまりありません。 –

0

あなたが探しているエレガントなSQLクエリではないかもしれませんが、結果を取得した後でJava、PHPなどで行うのは簡単です。できるだけシンプルにするには、ORDER BYのタイムスタンプDESCを使用して、最初の行を破棄します。

関連する問題