2016-10-07 5 views
1

Ich schaue mir eine SQL Server 2008-Datenbank mit zwei Tabellen an, jede mit einer PK (INT) -Spalte und einer DateTime-Spalte.Wie (Dirty) Pair Datetimes über zwei Tabellen

Es gibt keine explizite Beziehung zwischen den Tabellen, außer dass die Anwendung eine heuristische Tendenz hat, paarweise eine Zeile in die Datenbank einzufügen, mit DateTimes, die nie exakt übereinstimmen, aber normalerweise ziemlich nah sind.

Ich versuche, die PKs in jeder Tabelle zu sichern, indem Sie die am besten übereinstimmende DateTime in der anderen Tabelle finden. Jeder PK kann nur einmal für diesen Abgleich verwendet werden.

Was ist der beste Weg, dies zu tun?

EDIT: Entschuldigung, bitte finden Sie unten einige Beispiel Eingabe und gewünschte Ausgabe.

+-------+-------------------------+ 
| 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

'von t1 t2 auf t1.datetimecolumn zwischen dateadd (Minute, -1, t2.datetimecolumn) verbinden und dateadd (Minute, 1, t2.datetimecolumn);' –

+0

@AaronBertrand Danke für die schnelle Antwort, aber tut mir leid, dass ich nicht klar genug war. Ich klärte die Frage mit einigen Beispieleingaben und gewünschter Ausgabe. – Maarx

Antwort

2

JOIN zu der Zeile mit niedrigstem DATEDIFF (in Sekunden) zwischen t1.DateTime und t2.DateTime.

1

Sie können das Ergebnis, das Sie suchen, erreichen, indem Sie Tabelle 1 mit Tabelle 2 überschneiden und dann die Differenz der Daten in Sekunden gemäß dem Vorschlag von Tab Alleman erhalten. Der nächste Schritt wäre dann, jede Übereinstimmung mit der Funktion ROW_NUMBER() zu bewerten. Der letzte Schritt besteht darin, nur die Zeilen auszuwählen, die Rank = 1 sind. Das folgende Beispiel zeigt Ihr Beispiel Daten:

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