2017-07-03 3 views
0

私は、バージョン履歴を追跡するテーブルを持っています。テーブルの各IDの日付と共に最新バージョンのみを取得します。 以下は、ID、バージョンの組み合わせごとに最新の日付をお知らせします。トップレコードのみを選択するにはどうすればよいですか?私はこれを一時テーブルに保存してから、各ID、バージョンの組み合わせのトップレコードのみを取得するためにjoinを使用することができます。これを1ステップで達成するためのより良い方法はありますか?2つの列でグループ化された最新のレコードを取得するSQL Server

サンプル・データ

id version  timestamp 
123 1.5   2015-03-28 08:21:04.563 
123 1.0   2015-03-21 12:58:24.730 
234 1.5   2016-10-15 23:08:09.550 
345 1.5   2016-05-10 15:18:09.707 
345 1.5   2016-09-02 21:30:00.657 

の予想される出力

id version  timestamp 
123 1.5   2015-03-28 08:21:04.563 
234 1.5   2016-10-15 23:08:09.550 
345 1.5   2016-09-02 21:30:00.657 

クエリ

select id,version,max(dt_create) 
from version_history (nolock) 
group by id,version 
order by id 

私はこれを試してみましたが、私は

select * from 
( 
    select id,version,dt_create,row_number() over (partition by id,version order by dt_create desc) as a 
    from version_history (nolock) 
) b 
where a=1 
order by id 
上記と同じ結果を得ます

答えて

0

私はパーティション句からバージョンを削除した後に作品を持っている2番目のクエリで使用できる

select * from 
( 
    select id,version,dt_create,row_number() over (partition by id order by dt_create desc) as a 
    from version_history (nolock) 
) b 
where a=1 
order by id 
1

あなたはTIES句

Declare @YourTable Table ([id] int,[version] varchar(50),[timestamp] datetime) 
Insert Into @YourTable Values 
(123,1.5,'2015-03-28 08:21:04.563') 
,(123,1.0,'2015-03-21 12:58:24.730') 
,(234,1.5,'2016-10-15 23:08:09.550') 
,(345,1.5,'2016-05-10 15:18:09.707') 
,(345,1.5,'2016-09-02 21:30:00.657') 

Select Top 1 with ties * 
From @YourTable 
Order By Row_Number() over (Partition By ID Order By timestamp Desc) 

戻り

id version timestamp 
123 1.5  2015-03-28 08:21:04.563 
234 1.5  2016-10-15 23:08:09.550 
345 1.5  2016-09-02 21:30:00.657 
+0

Thanks.Myテーブル210万ドルを持っていますレコードとこれは40 +分を取っている。私は8分で結果を取得する参加を使用しています。 –

+0

@inquisitive_mindあなたには決心があります。データをテーブル変数にロードしない限り、なぜ40 +分が得られたのか想像できません。 –

1

私はあなたがパーティション分割でこれを達成できたのを見ていますが、別の方法を示したいと思います。あなたはあなた自身のためにパフォーマンスを比較し、最も速いものを見ることができます - (私はパーティション化が良いと仮定しています)。

まず、最新のバージョンであっても複数の日付が存在する可能性があることを知っていますので、各IDの最大バージョンは必要ありません。

まず、セットアップ:今すぐ

DECLARE @table TABLE (ID INT, [Version] DECIMAL(18, 2), [TimeStamp] DATETIME) 

INSERT INTO @table 
VALUES 
(123, 1.5, '2015-03-28 08:21:04.563'), 
(123, 1.5, '2015-03-21 12:58:24.730'), 
(234, 1.5, '2016-10-15 23:08:09.550'), 
(345, 1.5, '2016-05-10 15:18:09.707'), 
(345, 1.5, '2016-09-02 21:30:00.657') 

、最大日付で各IDを取得する:これは、私たちを与える

SELECT ID, 
     MAX([TimeStamp]) AS MaxTimeStamp 
FROM @table 
GROUP BY ID 

私たちが何をしたい:

ID   MaxTimeStamp 
----------- ----------------------- 
123   2015-03-28 08:21:04.563 
234   2016-10-15 23:08:09.550 
345   2016-09-02 21:30:00.657 

(3 row(s) affected) 

今ちょうどバージョンを含める必要があります。

SELECT T.ID, 
     MAX(T.[TimeStamp]) AS [MaxTimeStamp], 
     T2.[Version] AS [MaxVersion] 
FROM @table T 
JOIN @table T2 
    ON T.ID = T2.ID 
    AND T.[TimeStamp] = T2.[TimeStamp] 
GROUP BY T.ID, T2.[Version] 

そして、これは私たちに次のような結果得られます:私たちはIDと日付で、自己結合を行うことができますので、それは、簡単にする必要があります私たちは私たちの元のクエリに参加している

ID   MaxTimeStamp   MaxVersion 
----------- ----------------------- --------------------------------------- 
123   2015-03-28 08:21:04.563 1.50 
234   2016-10-15 23:08:09.550 1.50 
345   2016-09-02 21:30:00.657 1.50 

(3 row(s) affected) 

注意を同じテーブル - IDと日付で、議論のように。しかし、我々は今、バージョンを追加の列を選択しているので、それはあなたがCROSS APPLYを使用して同じ結果を得ることができ、またGROUP BY

に含まれる必要があります。

SELECT T.ID, 
     MAX(T.[TimeStamp]) AS MaxTimeStamp, 
     T2.[Version] 
FROM @table T 
CROSS APPLY 
    (
     SELECT Version 
     FROM @table T2 
     WHERE T2.ID = T.ID 
     AND T2.[TimeStamp] = T.[TimeStamp] 
    ) T2 
GROUP BY T.ID, T2.[Version] 
関連する問題