2012-03-16 52 views
0

我左表中的每一行在右表中只有一个匹配(右表是包含所有行的主表;左表仅包含这些行的子集)。每个表中的行的时间戳不完全匹配,但通常在彼此的1秒内。因此,当我加入表格时,我必须使用:如何防止INNER JOIN返回多个匹配?

FROM left_table INNER JOIN right_table 
ON left_table.timestamp BETWEEN right_table.timestamp - .00015 AND right_table.timestamp + .00015 
--This is approximately a 2 second wide range since this is a DATETIME field 
AND left_table.name = right_table.name 
AND ........ 

除时间戳之外,其他所有条件都完全匹配。有没有解决的办法?

大多数情况下,这足以返回只有一行,但有时当一秒钟内有两个相同的行时,它们都会被返回。

+1

你可以尝试不同的,或TOP 1. – 2012-03-16 21:15:35

+2

在您的where子句中的好方法,你的意思是 打开之间right_table.timestamp left_table.timestamp - 。 00015 AND right_table.timestamp + .00015 – David 2012-03-16 21:21:04

+0

我想这就是我要做的。我只是重新评估了这个问题,我认为只要我使用“DISTINCT”就可以返回多个结果。时间跨度非常狭窄,以至于我需要从连接中获取标准。谢谢! – eek142 2012-03-16 21:22:21

回答

1

如果您只需要精确到秒,就可以截断您选择的其余部分。

2

这应该更准确。现在获得受骗者的唯一方法是,如果他们都具有相同的时间差:

FROM left_table 
INNER JOIN 
    (
    SELECT l.name, min(abs(r.timestamp - l.timestamp)) as offset 
    FROM left_table l 
    INNER JOIN right_table ON r on r.name=l.name 
    GROUP BY l.name 
) lrmap ON left_table.name = lrmap.name 
INNER JOIN right_table 
ON left_table.name = right_table.name 
    AND abs(left_table.timestamp-right_table.timestamp) = lrmap.offset 

我不会担保的性能,不过,因为减法是缓慢的,并把他们的ABS()函数内杀死任何在这些列上使用索引的机会。如果我有更多时间可以花费,我可能会把一些东西放在一起,这会对索引更友好......但也许不是,因为这对我来说看起来像是弱桌面设计,真正的解决方法是添加一列更直接地链接记录。

+0

我很欣赏这种努力。我会再看看这个,但我认为DISTINCT现在可以满足我的需求。 – eek142 2012-03-16 21:34:48

0

一个where exists()条款是为了防止笛卡尔乘积

FROM left_table lt 
where exists(
    select 1 from right_table 
    where lt.[timestamp] BETWEEN [timestamp] - .00015 AND [timestamp] + .00015 
    and lt.name=name 
    AND ........ 
) 
AND ........