Как запретить INNER JOIN возвращать несколько совпадений? - PullRequest
0 голосов
/ 17 марта 2012

Каждая строка в моей таблице слева должна иметь только одно совпадение в таблице справа (правая таблица является основной таблицей со всеми строками в ней; левая таблица содержит только подмножество этих строк).Временные метки строк в каждой таблице не совпадают точно, но обычно они находятся в пределах 1 секунды друг от друга.Поэтому, когда я присоединяюсь к таблицам, я должен использовать:

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 строку, но иногда, когда в одной секунде находятся две одинаковые строки, они оба возвращаются.

Ответы [ 3 ]

2 голосов
/ 17 марта 2012

Это должно быть более точным. Единственный способ получить дубликаты сейчас, если они оба имеют одинаковую разницу во времени:

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 () убивает любую возможность использования индексов для этих столбцов. Если бы у меня было больше времени, я мог бы собрать что-то более удобное для индекса ... но, возможно, нет, потому что для меня это выглядит как слабый дизайн таблицы, и реальным решением было бы добавить столбец более прямые ссылки на записи.

1 голос
/ 17 марта 2012

Если вам нужна только точность с точностью до секунды, вы можете усечь все остальное в своем выборе.

0 голосов
/ 17 марта 2012
Предложение

A 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 ........
...