2016-10-07 4 views
1

Я смотрю базу данных SQL Server 2008 с двумя таблицами, каждая с столбцом PK (INT) и столбцом DateTime.Как (Dirty) Пара DateTimes по двум таблицам

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

Я пытаюсь сопоставить резервные копии ПК в каждой таблице, найдя ближайшую совпадающую дату DateTime в другой таблице. Каждый PK может использоваться только один раз для этого соответствия.

Каков наилучший способ для этого?

EDIT: Извините, пожалуйста, найдите внизу пример ввода и желаемого вывода.

+-------+-------------------------+ 
| t1.PK |  t1.DateTime  | 
+-------+-------------------------+ 
|  1 | 2016-08-11 00:11:03.000 | 
|  2 | 2016-08-11 00:11:08.000 | 
|  3 | 2016-08-11 11:03:00.000 | 
|  4 | 2016-08-11 11:08:00.000 | 
+-------+-------------------------+ 

+-------+-------------------------+ 
| t2.PK |  t2.DateTime  | 
+-------+-------------------------+ 
|  1 | 2016-08-11 11:02:00.000 | 
|  2 | 2016-08-11 00:11:02.000 | 
|  3 | 2016-08-11 22:00:00.000 | 
|  4 | 2016-08-11 11:07:00.000 | 
|  5 | 2016-08-11 00:11:07.000 | 
+-------+-------------------------+ 

+-------+-------+-------------------------+-------------------------+ 
| t1.PK | t2.PK |  t1.DateTime  |  t2.DateTime  | 
+-------+-------+-------------------------+-------------------------+ 
|  1 |  2 | 2016-08-11 00:11:03.000 | 2016-08-11 00:11:02.000 | 
|  2 |  5 | 2016-08-11 00:11:08.000 | 2016-08-11 00:11:07.000 | 
|  3 |  1 | 2016-08-11 11:03:00.000 | 2016-08-11 11:02:00.000 | 
|  4 |  4 | 2016-08-11 11:08:00.000 | 2016-08-11 11:07:00.000 | 
+-------+-------+-------------------------+-------------------------+ 
+2

'из t1 t2 присоединиться на t1.datetimecolumn между DateAdd (минута, -1, t2.datetimecolumn) и DATEADD (минута, 1, t2.datetimecolumn);' –

+0

@AaronBertrand Спасибо за быстрый ответ, но извините, что я не был достаточно ясен. Я уточнил вопрос с помощью некоторого ввода образца и желаемого вывода. – Maarx

ответ

2

РЕГИСТРИРУЙТЕСЬ к ряду с низкой DATEDIFF (в секундах) между t1.DateTime и t2.DateTime.

1

Вы можете достичь результата, который вы ищете, с помощью таблицы перекрестного соединения 1 со столом 2, а затем получения разницы между датами в секундах в соответствии с предложением Tab Alleman. Следующим шагом было бы ранжирование каждого матча с помощью функции ROW_NUMBER(). Конечным шагом является выбор только строк, которые Rank = 1. Следующий пример демонстрирует с помощью примера данные:

DECLARE @t1 TABLE 
(
    ID   INT PRIMARY KEY 
    ,[DateTime] DATETIME 
); 

DECLARE @t2 TABLE 
(
    ID   INT PRIMARY KEY 
    ,[DateTime] DATETIME 
) 

INSERT INTO @t1 
(
    ID   
    ,[DateTime] 
) 
VALUES 
(1 ,'2016-08-11 00:11:03.000'), 
(2 ,'2016-08-11 00:11:08.000'), 
(3 ,'2016-08-11 11:03:00.000'), 
(4 ,'2016-08-11 11:08:00.000'); 

INSERT INTO @t2 
(
    ID   
    ,[DateTime] 
) 
VALUES 
(1, '2016-08-11 11:02:00.000'), 
(2, '2016-08-11 00:11:02.000'), 
(3, '2016-08-11 22:00:00.000'), 
(4, '2016-08-11 11:07:00.000'), 
(5, '2016-08-11 00:11:07.000'); 


WITH CTE_DateDifference 
AS 
(
    SELECT  t1.ID AS T1_ID 
       ,t2.ID AS T2_ID 
       ,t1.[DateTime] AS T1_DateTime 
       ,t2.[DateTime] AS T2_DateTime 
       ,ABS(DATEDIFF(SECOND, t1.[DateTime], t2.[DateTime])) AS Duration -- Determine the difference between the dates in seconds. 
    FROM  @t1 t1 
    CROSS JOIN @t2 t2 
),CTE_RankDateMatch 
AS 
(
    SELECT T1_ID 
      ,T2_ID 
      ,T1_DateTime 
      ,T2_DateTime 
      ,ROW_NUMBER() OVER (PARTITION BY T1_ID ORDER BY Duration) AS [Rank] -- Rank each match, the row numbers generated will be order based on the duration between the dates. Thus rows with a number of 1will be the closest match between the two tables. 
    FROM CTE_DateDifference 
) 
-- Finally select out the rows with a Rank equal to 1. 
SELECT * 
FROM CTE_RankDateMatch 
WHERE [Rank] = 1 
Смежные вопросы