2010-05-11 44 views
1

我有两个表在差不多更新完全相同的时间 - 我需要加入的日期时间列。SQL - 如何加入类似的(不是确切的)列

我已经试过这样:

SELECT * 
FROM A, B 
WHERE ABS(DATEDIFF(second, A.Date_Time, B.Date_Time)) = (
    SELECT MIN(ABS(DATEDIFF(second, A.Date_Time, B2.Date_Time))) 
    FROM B AS B2 
) 

但它告诉我:

多个列中包含外部引用的被聚合表达式中指定。如果要汇总的表达式包含外部引用,那么该外部引用必须是表达式中引用的唯一列。

我该如何加入这些表格?

回答

4

如何像(假设SQL 2005+):

With RankedItems As 
    (
    Select A.DateTime As ADateTime, B.DateTime As BDateTime 
     , ROW_NUMBER() OVER (PARTITION BY A.DateTime ORDER BY ABS(DateDiff(s, A.DateTime, B.DateTime))) As ItemRank 
    From A 
     Cross Join B 
    ) 
Select 
From RankedItems 
Where ItemRank = 1 

在我的解决方案,我用了很短的公共表表达式或CTE。在CTE中,我使用了排序函数(ROW_NUMBER),它可以计算CTE表达式中的每一行。 ROW_NUMBER函数将返回为表A中的每个DateTime值提供一个顺序整数,通过PARTITION BY A.DateTime子句按“紧密度”A.DateTime值到B.DateTime值的绝对值排序。因此,我使用Abs(DateDiff(s,A.DateTime, B.DateTime)并为每个A.DateTime值选择最高排名(排名= 1,又名“最接近”值),将排名“接近”。因为ROW_NUMBER()函数将为每个A.DateTime值返回一个唯一的数字列表,所以没有关系。

+0

你能解释一下这段代码的工作原理吗?我从来没有见过很多这样的构造。 – 2010-05-11 21:36:20

+0

@BlueRaja - 我已经扩展了我的答案以提供更多细节。 – Thomas 2010-05-11 23:14:19

+0

我最终在查询中用'TOP 1 ... ORDER BY Date_Time'取代了'MIN',但是这个答案教会了我一些新的东西,并且帮助我解决了一个相关的问题(找到了一个特定列更改的行尊重上一行,按日期排序)。谢谢! – 2010-05-12 13:42:01

2

首先创建一个包含保存您计算的datediff的列的视图,然后从中构建查询可能会更好。

3

这是你想要的吗?它会检查1秒差

select * from 
A, b --use a join next time 
where A.Date_Time 
between DATEADD(s,-1,B.Date_Time) and DATEADD(s,1,B.Date_Time) 
+0

我想加入A行的每一行与最近的Date_Time值的B行。它不一定总是在1秒内 – 2010-05-11 20:28:44