2012-12-24 17 views
18

テーブルdbo.XDateTimecolumn Yがあり、数百ものレコードが含まれている可能性があります。SQL Serverで最も近い日付を検索

私のストアドプロシージャは、パラメータ@CurrentDateを持って、私はどのようにそれを見つけることが@CurrentDate.

に最も近いよりも小さい上記の表dbo.Xcolumn Yの日付を知りたいですか?その日、何の間にある日数または秒によって

答えて

48

ザ・@CurrentDate、およびそれらが子孫順に並べられているため、TOP 1は現在の日付に最も近い日付になります。

SELECT TOP 1 * 
FROM x 
WHERE x.date < @CurrentDate 
ORDER BY x.date DESC 
+1

しかし、それはどのくらい効率的ですか? – MaxRecursion

+1

データベースの設計によって異なります。私はあなたのテーブルの日付フィールドのインデックスを設定しようとすると、システムは直接クエリに一致する値のために行くことができるようにすることをお勧めします。 – ederbf

+0

助けてくれてありがとう。 – MaxRecursion

7

使用DateDiffとあなたの結果を注文入力された

ような何か、この句は以下の日付を持つすべての行と一致します

select top 1 rowId, dateCol, datediff(second, @CurrentDate, dateCol) as SecondsBetweenDates 
    from myTable 
    where dateCol < @currentDate 
    order by datediff(second, @CurrentDate, dateCol) 
+3

ORDER BYでは、別名で列を参照できます(つまり、「ORDER BY SecondsBetweenDate」)。ただし、行ではなく式で行をソートしています。これは、クエリを非[sargable](http://ja.wikipedia.org/wiki/Sargable "Sargable(Wikipedia)")にする可能性があります。ただのメモ。 –

+0

@AndriyMああ、それを知らなかった、チップのおかげで –

-7
CREATE PROCEDURE CurrentDate 
@CurrentDate DATETIME 
AS 
BEGIN 
    Select * from orders 
    where OrderDate < @CurrentDate 
END 
GO 
-1

私は私が考えるこの問題のより良い解決策を持っています。

最終的な解決方法をサポートし説明するための画像をいくつか示します。

背景 私の解決策で私はFXレートのテーブルを持っています。これらは、異なる通貨の市場金利を表しています。しかし、当社のサービスプロバイダはレートフィードに問題があり、そのようなレートにはゼロ値があります。私は欠けているデータを、欠けているレートに最も近い時間と同じ通貨のレートで埋めることを望みます。基本的には、最も近いゼロ以外のレートのRateIdを取得したいのですが、それを私が代用します。 (これは私の例では、ここで示されていない)

1)だから、オフを開始するには、不足している料金情報を識別することができます:

Query showing my missing rates i.e. have a rate value of zero

2)次欠落していない速度を識別することができます。 Query showing rates that are not missing

3)このクエリは、魔法の発生場所です。私はここでは削除することができますが、クエリの効率/パフォーマンスを向上させるために追加されたことを前提にしています。 26行目の前提は、紛失/ゼロ取引と同じ日に代替取引を見つけることが予想されることです。 マジックは行23です:Row_Number関数は、欠落しているトランザクションと欠落していないトランザクションの間の最短時間差を1とする自動番号を追加します。次の最も近い取引には2の円があります。

25行目では、通貨タイプが一致しないように通貨を参加させる必要があります。それは私がCHF値でAUD通貨を代用したくないということです。私は最も近い一致する通貨が欲しいです。

Combining the two data sets with a row_number to identify nearest transaction

4)最後に、ROWNUMは、次のようにクエリ完全クエリは1 The final query

あるデータを取得することができます。

; with cte_zero_rates as 
(
     Select  * 
     from  fxrates 
     where  (spot_exp = 0 or spot_exp = 0) 
), 
cte_non_zero_rates as 
(
     Select  * 
     from  fxrates 
     where  (spot_exp > 0 and spot_exp > 0) 
) 
,cte_Nearest_Transaction as 
(
     select  z.FXRatesID as Zero_FXRatesID 
        ,z.importDate as Zero_importDate 
        ,z.currency  as Zero_Currency 
        ,nz.currency as NonZero_Currency 
        ,nz.FXRatesID as NonZero_FXRatesID 
        ,nz.spot_imp 
        ,nz.importDate as NonZero_importDate 
        ,DATEDIFF(ss, z.importDate, nz.importDate) as TimeDifferece 
        ,ROW_NUMBER() Over(partition by z.FXRatesID order by abs(DATEDIFF(ss, z.importDate, nz.importDate)) asc) as RowNum 
     from  cte_zero_rates z 
     left join cte_non_zero_rates nz on nz.currency = z.currency 
        and cast(nz.importDate as date) = cast(z.importDate as date) 
     --order by z.currency desc, z.importDate desc 
) 
select   n.Zero_FXRatesID 
       ,n.Zero_Currency 
       ,n.Zero_importDate 
       ,n.NonZero_importDate 
       ,DATEDIFF(s, n.NonZero_importDate,n.Zero_importDate) as Delay_In_Seconds 
       ,n.NonZero_Currency 
       ,n.NonZero_FXRatesID 
from   cte_Nearest_Transaction n 
where   n.RowNum = 1 
       and n.NonZero_FXRatesID is not null 
order by  n.Zero_Currency, n.NonZero_importDate 
関連する問題