Присоединение к полю datetime SQL Server - PullRequest
0 голосов
/ 15 июня 2009

У меня есть две таблицы, в которых хранится информация для SKU.

В таблице журнала есть поле datetime 2008-10-26 06: 21: 59.820
другая таблица имеет поле datetime 2008-10-26 06: 22: 02.313

Я хочу включить эти поля даты и времени в объединение для этих 2 таблиц.

Можно ли объединить таблицы с полями даты и времени, разница которых не превышает 3 секунд? Каков наилучший способ сделать это?

Ответы [ 7 ]

7 голосов
/ 15 июня 2009

Это один из способов сделать это:

select * from table_a, table_b
where table_a.sku = table_b.sku
and abs(datediff(second,table_a.datetime,table_b.datetime))<=3

Будьте осторожны, с большими столами такой тип соединения может быть очень медленным.

5 голосов
/ 15 июня 2009
SELECT
  t1.id,
  t2.id
FROM
  t1
  INNER JOIN t2 ON ABS(DATEDIFF(ms, t1.datefield, t2.datefield)) <= 3000
WHERE
  ...

Осторожно, это будет медленно. И, вероятно, не всегда верно (как в: он не всегда объединяет записи, которые должны быть объединены, потому что они принадлежат друг другу, это, конечно, всегда будет технически правильно).

РЕДАКТИРОВАТЬ:

Изменено с ABS(DATEDIFF(ss, t1.datefield, t2.datefield)) <= 3 на вышеприведенное из-за превосходного наблюдения @ richardtallent в комментариях.

2 голосов
/ 15 июня 2009

Трудно сделать это эффективно, потому что вы в конечном итоге делаете запросы, используя выражения, а не значения полей напрямую, и такие запросы не используют индексы хорошо.

В частности, не используйте DATEDIFF.

У вас может быть шанс с

ГДЕ DATEADD (мс, дата1, 3) <дата2 И DATEADD (мс, дата1, -3)> дата2

или

ГДЕ date2 МЕЖДУ DATEADD (мс, date1, 3) И DATEADD (мс, date1, -3)

Примечание. Обычно можно реорганизовать вставки так, чтобы они имели одинаковые значения меток времени, если они получены из одного и того же события или транзакции (но тогда у них будет какой-то другой общий ключ, и вам не потребуется это делать). 1013 *

Вы также можете хранить исходное значение в более низком разрешении - скажем, полную секунду или даже минуту - в зависимости от ваших требований, но тогда у вас все равно будут проблемы с границами.

2 голосов
/ 15 июня 2009

На ум приходят два пути:

... on other.date between dateadd(second,-3,log.date) and dateadd(second,3,log.date)

и

... on abs(datediff(millisecond, other.date, log.date)) <= 3000

Проверьте, какой из них дает наилучшую производительность.

(Редактировать: во втором варианте секунды заменены на миллисекунды, как указал Ричардталент в комментарии к другому ответу.)

1 голос
/ 15 июня 2009

Можете ли вы зависеть от порядка значений даты и времени для строк, которые должны совпадать? Например, всегда ли запись журнала предшествует записи в другой таблице? Если это так, измените один из ответов выше, чтобы удалить функцию ABS () (особенно учитывая порядок параметров DATEDIFF). Это поможет предотвратить ложные совпадения.

0 голосов
/ 15 июня 2009

Не проверено, но это должно работать ...

Select *
From tbl1
  inner join tbl2 on tbl1.id=tbl2.id and 
     Datediff(second, tbl1.dttime, tbl2.dttime) between -3 and 3
0 голосов
/ 15 июня 2009
SELECT tbl1.*, tbl2.*
FROM tbl1, tbl2
WHERE ABS(DATEDIFF(second, tb1.date, tbl2.date)) <= 3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...