如何(脏)对两个表中的日期时间

时间:2016-10-07 17:20:59

标签: sql-server tsql datetime

我正在查看带有两个表的SQL Server 2008数据库,每个表都有一个PK(INT)列和一个DateTime列。

表之间没有明确的关系,除了我知道应用程序具有成对插入数据库的启发式趋势,每行中有一行,DateTimes似乎永远不会完全匹配,但通常非常接近。 / p>

我试图通过在另一个表中找到最接近的匹配DateTime来匹配每个表中的PK。每个PK只能用于此匹配。

这样做的最佳方式是什么?

编辑:对不起,请在底部找到一些示例输入和所需的输出。

+-------+-------------------------+
| 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 个答案:

答案 0 :(得分:2)

加入t1.DateTimet2.DateTime之间DATEDIFF最低(以秒为单位)的行。

答案 1 :(得分: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