web-dev-qa-db-ja.com

SQL Serverで最も近い日付を見つける

テーブルdbo.XDateTimecolumn Yがあり、何百ものレコードがある場合があります。

ストアドプロシージャにはパラメータ@CurrentDateがあります。上記の表のcolumn Yの日付を見つけたいdbo.X@CurrentDate.より小さく、最も近いです

どうやって見つけるの?

28
MaxRecursion

Where句は、@ CurrentDateより小さい日付を持つすべての行に一致します。これらの行は子孫であるため、TOP 1は現在の日付に最も近い日付になります。

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

DateDiff を使用して、その日付と入力が何であったかの間の日数または秒数で結果を並べます

このようなもの

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

私はこの問題に対してより良い解決策があると思います。

最終的なソリューションをサポートおよび説明するために、いくつかの画像を示します。

背景私のソリューションにはFXレートの表があります。これらは、異なる通貨の市場レートを表します。ただし、サービスプロバイダーにはレートフィードに問題があり、そのため一部のレートの値はゼロになっています。欠落しているデータに、欠落しているレートに時間的に最も近い同じ通貨のレートを入力します。基本的に、最も近い非ゼロレートのRateIdを取得し、それを代入します。 (これは私の例では示されていません。)

1)そのため、まずは欠落している料金情報を特定します:

欠落しているレートを示すクエリ、つまりレート値がゼロ

2)次に、欠落していないレートを特定します。欠落していないレートを示すクエリ

3)このクエリは、魔法が発生する場所です。ここでは、削除できると仮定しましたが、クエリの効率/パフォーマンスを改善するために追加されました。行26の前提は、欠落/ゼロトランザクションと同じ日に代替トランザクションを見つけることです。魔法が起こるのは23行目です。Row_Number関数は、欠落しているトランザクションと欠落していないトランザクションの時間差が最短になるように、1から始まる自動番号を追加します。次に近いトランザクションのrownumは2などです。

25行目では、通貨の種類が一致しないように通貨を結合する必要があることに注意してください。つまり、AUD通貨をCHF値に置き換えたくありません。最も近い通貨が欲しい。

2つのデータセットをrow_numberと組み合わせて、最も近いトランザクションを識別する

4)最後に、RowNumが1であるデータを取得します最終クエリ

クエリの完全なクエリは次のとおりです。

    ; 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
0
Craig Gers