我有两个表,一个持有最近的一个位置值,另一个是一个包含所有其他值的存档。我想构建一个查询,选择最接近传入日期的位置值。 最近的日期将始终位于“职位”表中,旧的所有内容将始终位于存档中。 现在有一个约会者,查看最新表或日期存档表中的日期是否更近,然后选择哪一个。我正在寻找一种更简单的方法,可以在连接中实现这一点。选择 正如您在下面看到的,这个查询不太好。试图想出一个在连接中做到这一点的方法。 最接近的日期将等于或未来的日期过去。所以下面的例子我预计将获得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
答案 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