テーブルdbo.X
とDateTime
column Y
があり、数百ものレコードが含まれている可能性があります。SQL Serverで最も近い日付を検索
私のストアドプロシージャは、パラメータ@CurrentDate
を持って、私はどのようにそれを見つけることが@CurrentDate.
に最も近いよりも小さい上記の表dbo.X
でcolumn Y
の日付を知りたいですか?その日、何の間にある日数または秒によって
テーブルdbo.X
とDateTime
column Y
があり、数百ものレコードが含まれている可能性があります。SQL Serverで最も近い日付を検索
私のストアドプロシージャは、パラメータ@CurrentDate
を持って、私はどのようにそれを見つけることが@CurrentDate.
に最も近いよりも小さい上記の表dbo.X
でcolumn Y
の日付を知りたいですか?その日、何の間にある日数または秒によって
ザ・@CurrentDate、およびそれらが子孫順に並べられているため、TOP 1は現在の日付に最も近い日付になります。
SELECT TOP 1 *
FROM x
WHERE x.date < @CurrentDate
ORDER BY x.date DESC
使用DateDiffとあなたの結果を注文入力された
ような何か、この句は以下の日付を持つすべての行と一致します
select top 1 rowId, dateCol, datediff(second, @CurrentDate, dateCol) as SecondsBetweenDates
from myTable
where dateCol < @currentDate
order by datediff(second, @CurrentDate, dateCol)
ORDER BYでは、別名で列を参照できます(つまり、「ORDER BY SecondsBetweenDate」)。ただし、行ではなく式で行をソートしています。これは、クエリを非[sargable](http://ja.wikipedia.org/wiki/Sargable "Sargable(Wikipedia)")にする可能性があります。ただのメモ。 –
@AndriyMああ、それを知らなかった、チップのおかげで –
CREATE PROCEDURE CurrentDate
@CurrentDate DATETIME
AS
BEGIN
Select * from orders
where OrderDate < @CurrentDate
END
GO
私は私が考えるこの問題のより良い解決策を持っています。
最終的な解決方法をサポートし説明するための画像をいくつか示します。
背景 私の解決策で私は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
しかし、それはどのくらい効率的ですか? – MaxRecursion
データベースの設計によって異なります。私はあなたのテーブルの日付フィールドのインデックスを設定しようとすると、システムは直接クエリに一致する値のために行くことができるようにすることをお勧めします。 – ederbf
助けてくれてありがとう。 – MaxRecursion