简体   繁体   English

在SQL Server中查找最接近的日期

[英]Find closest date in SQL Server

I have a table dbo.X with DateTime column Y which may have hundreds of records. 我有一个表dbo.XDateTime column Y ,可能有数百条记录。

My Stored Procedure has parameter @CurrentDate , I want to find out the date in the column Y in above table dbo.X which is less than and closest to @CurrentDate. 我的存储过程有参数@CurrentDate ,我想找出上面表dbo.X column Y的日期,该日期小于且最接近@CurrentDate.

How to find it? 怎么找到它?

The where clause will match all rows with date less than @CurrentDate and, since they are ordered descendantly, the TOP 1 will be the closest date to the current date. where子句将匹配日期小于@CurrentDate的所有行,并且由于它们是后续排序的,因此TOP 1将是与当前日期最接近的日期。

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

Use DateDiff and order your result by how many days or seconds are between that date and what the Input was 使用DateDiff并按结果显示该日期与输入之间的天数或秒数

Something like this 像这样的东西

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

I have a better solution for this problem i think. 我认为我有更好的解决方案。

I will show a few images to support and explain the final solution. 我将展示一些图像来支持和解释最终的解决方案。

Background In my solution I have a table of FX Rates. 背景在我的解决方案中,我有一个外汇汇率表。 These represent market rates for different currencies. 这些代表不同货币的市场汇率。 However, our service provider has had a problem with the rate feed and as such some rates have zero values. 但是,我们的服务提供商在费率Feed方面存在问题,因此某些费率的值为零。 I want to fill the missing data with rates for that same currency that as closest in time to the missing rate. 我想用相同货币的汇率填补缺失的数据,这些汇率最接近缺失的汇率。 Basically I want to get the RateId for the nearest non zero rate which I will then substitute. 基本上我想得到最接近的非零利率的RateId,然后我将替换。 (This is not shown here in my example.) (这在我的例子中没有显示。)

1) So to start off lets identify the missing rates information: 1)因此,开始时我们可以识别丢失的费率信息:

Query showing my missing rates ie have a rate value of zero 查询显示我的遗漏率,即费率值为零

2) Next lets identify rates that are not missing. 2)接下来让我们确定不缺少的费率。 Query showing rates that are not missing 查询显示未丢失的费率

3) This query is where the magic happens. 3)这个查询是神奇发生的地方。 I have made an assumption here which can be removed but was added to improve the efficiency/performance of the query. 我在这里做了一个假设,可以删除但添加它以提高查询的效率/性能。 The assumption on line 26 is that I expect to find a substitute transaction on the same day as that of the missing / zero transaction. 第26行的假设是我希望在缺失/零交易的同一天找到替代交易。 The magic happens is line 23: The Row_Number function adds an auto number starting at 1 for the shortest time difference between the missing and non missing transaction. 神奇的事情发生在第23行:Row_Number函数添加一个从1开始的自动编号,用于缺失和非缺失事务之间的最短时间差。 The next closest transaction has a rownum of 2 etc. 下一个最接近的交易的rownum为2等。

Please note that in line 25 I must join the currencies so that I do not mismatch the currency types. 请注意,在第25行,我必须加入货币,以便我不会使货币类型不匹配。 That is I don't want to substitute a AUD currency with CHF values. 那就是我不想用CHF值替换澳元货币。 I want the closest matching currencies. 我想要最接近的匹配货币。

Combining the two data sets with a row_number to identify nearest transaction 将两个数据集与row_number组合以标识最近的事务

4) Finally, lets get data where the RowNum is 1 The final query 4)最后,让我们获取RowNum为1 的数据最终查询

The query full query is as follows; 查询完整查询如下;

    ; 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
CREATE PROCEDURE CurrentDate
@CurrentDate DATETIME
AS
BEGIN
    Select * from orders
    where OrderDate < @CurrentDate
END
GO

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM