选择最接近日期的日期记录

时间:2014-11-07 22:05:16

标签: sql sql-server select join parameters

我有两个表,一个持有最近的一个位置值,另一个是一个包含所有其他值的存档。我想构建一个查询,选择最接近传入日期的位置值。 最近的日期将始终位于“职位”表中,旧的所有内容将始终位于存档中。 现在有一个约会者,查看最新表或日期存档表中的日期是否更近,然后选择哪一个。我正在寻找一种更简单的方法,可以在连接中实现这一点。选择 正如您在下面看到的,这个查询不太好。试图想出一个在连接中做到这一点的方法。 最接近的日期将等于或未来的日期过去。所以下面的例子我预计将获得2014-04-06 75800.00的支持1714和2013-11-05的950.00回到2240 编辑:SQL SERVER 2008R2

DECLARE @dtAsOFDate DATETIME= '2014-04-11'

select a.iID
 ,mp.iposid
 ,CASE WHEN DATEDIFF(DAY,mp.dtASOfDate,@dtASOfdate) <= ISNULL(DATEDIFF(DAY,mpa.dtASOfDate,@dtASOfdate),999999) 
                    AND DATEDIFF(DAY,mp.dtASOfDate,@dtASOfDate)>=0 
                                    THEN mp.dtAsOfDate 
                                    ELSE mpa.dtAsOFDate END 
,CASE WHEN DATEDIFF(DAY,mp.dtASOfDate,@dtASOfdate) <= ISNULL(DATEDIFF(DAY,mpa.dtASOfDate,@dtASOfdate),999999) 
                    AND DATEDIFF(DAY,mp.dtASOfDate,@dtASOfDate)>=0 
                                    THEN mp.mPosValue 
                                    ELSE mpa.mPosValue END 


from #accountIDs a with (nolock)
join positions p with (nolock)on mp.iaccountid=a.iaccountid
left join positionsarchive mpa with (nolock) on mp.iposid=mpa.iposid
AND mpa.dtASOfdate=(SELECT max(dtASOfDate) FROM dbo.PositionsArchive WITH (NOLOCK) WHERE     mpa.iID=iID and mpa.iPosID=iPosID and dtASOfDate<=@dtASOfDate)

示例数据:

iID iPosID MostRecentDate MostRecentValue ArchiveDate ArchiveValue

-1427770 1714 2014-04-06 75800.00 2014-04-02 67800.00

-1529470 2240 2014-11-05 95.00 2013-11-05 950.00

2 个答案:

答案 0 :(得分:0)

我认为outer apply就是这样。类似于以下查询:

DECLARE @dtAsOFDate DATETIME= '2014-04-11';

select a.iaccountid, mp.imanualposid,
       (CASE WHEN ABS(DATEDIFF(DAY, mp.dtASOfDate, @dtASOfdate)) >
                  ABS(DATEDIFF(DAY, mpa.dtASOfDate, @dtASOfdate))
              THEN mpa.dtAsOFDate ELSE mp.dtAsOfDate 
        END) as ClosestDate
from #accountIDs a with (nolock) join
     manualpositions mp with (nolock)
     on mp.iaccountid = a.iaccountid outer apply
     (select top 1 mpa.*
      from manualpositionsarchive mpa with (nolock)
      where mp.imanualposid = mpa.imanualposid
      order by abs(datediff(day, mpa.dtAsOfDate, @dtAsOfDate) )
     ) mpa

编辑:

如果您希望最近的日期小于或等于,则查询将非常相似:

select a.iaccountid, mp.imanualposid,
       (CASE WHEN mp.dtASOfDate > @dtASOfdate
             THEN mp.dtAsOfDate 
             ELSE mpa.dtAsOFDate
        END) as ClosestDate
from #accountIDs a with (nolock) join
     manualpositions mp with (nolock)
     on mp.iaccountid = a.iaccountid outer apply
     (select top 1 mpa.*
      from manualpositionsarchive mpa with (nolock)
      where mp.imanualposid = mpa.imanualposid and mpa.dtAsOfDate < @dtAsOfDate
      order by mpa.dtAsOfDate desc
     ) mpa

答案 1 :(得分:0)

试试这个。

DECLARE @dtAsOFDate DATETIME = '2014-04-11'

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;       --Easier to employ than WITH (NOLOCK)

; WITH
    CTE1 AS
    (
        SELECT
            a.iaccountid
            , mp.imanualposid
            , mp.dtAsOfDate
            , mp.mPosValue
            , ABS(DATEDIFF(DAY,mp.dtASOfDate,@dtASOfdate)) AS daysAway
        FROM #accountIDs a
            INNER JOIN manualpositions mp ON mp.iaccountid = a.iaccountid
        WHERE mp.iAccountID = a.iaccountid
        UNION SELECT
            a.iaccountid
            , mpa.imanualposid
            , mpa.dtAsOfDate
            , mpa.mPosValue
            , ABS(DATEDIFF(DAY,mpa.dtASOfDate,@dtASOfdate)) AS daysAway
        FROM #accountIDs a
            INNER JOIN manualpositionsarchive mpa ON mpa.iaccountid = a.iaccountid
        WHERE mpa.iAccountID = a.iaccountid
    )
    ,
    CTE2 AS
    (
        SELECT
            iaccountid
            , imanualposid
            , dtAsOfDate
            , mPosValue
            , RowNumber = ROW_NUMBER() OVER (PARTITION BY imanualposid ORDER BY daysAway ASC)
        FROM CTE1
    )
SELECT
    iaccountid
    , imanualposid
    , dtAsOfDate
    , mPosValue
FROM CTE2
WHERE RowNumber = 1
ORDER BY
    iaccountid ASC
    , imanualposid ASC