使用内部联接与最近的DateTime匹配更新查询

Moo*_*ght 2 sql-server datetime sql-update

我有以下两个表

CREATE TABLE Ep
    ([E] varchar(9), [M] varchar(9), [DTE] DATETIME)
;

INSERT INTO Ep
    ([E], [M], [DTE])
VALUES
    ('1595861-1', '1595861-1', CONVERT(datetime, '2002-11-26 14:18:00', 20)),
    ('1595904-1', '1595904-1', CONVERT(datetime, '2002-11-24 15:15:00', 20)),
    ('1596298-1', '1596298-1', CONVERT(datetime, '2002-12-17 11:12:00', 20)),
    ('1596357-1', '1596357-1', CONVERT(datetime, '2002-12-09 19:57:00', 20)),
    ('1596369-1', '1596369-1', CONVERT(datetime, '2002-12-11 06:00:00', 20)),
    ('1596370-1', '1596370-1', CONVERT(datetime, '2002-12-19 12:31:00', 20)),
    ('1596473-2', '1596473-1', CONVERT(datetime, '2002-12-15 08:39:00', 20)),
    ('1596473-3', '1596473-1', CONVERT(datetime, '2002-12-20 08:39:00', 20)),
    ('1596473-4', '1596473-1', CONVERT(datetime, '2002-12-13 08:39:00', 20)),
    ('1596473-5', '1596473-1', CONVERT(datetime, '2002-12-16 08:39:00', 20)),
    ('1596473-1', '1596473-1', CONVERT(datetime, '2002-12-14 08:39:00', 20))
;

CREATE TABLE Mp
    ([E] varchar(9), [M] varchar(9), [DTE] DATETIME)
;

INSERT INTO Mp
    ([E], [M], [DTE])
VALUES
    ('', '1595861-1', CONVERT(datetime, '2002-11-26 14:18:00', 20)),
    ('', '1595904-1', CONVERT(datetime, '2002-11-24 15:15:00', 20)),
    ('', '1596298-1', CONVERT(datetime, '2002-12-17 11:12:00', 20)),
    ('', '1596357-1', CONVERT(datetime, '2002-12-09 19:57:00', 20)),
    ('', '1596369-1', CONVERT(datetime, '2002-12-11 06:00:00', 20)),
    ('', '1596370-1', CONVERT(datetime, '2002-12-19 12:31:00', 20)),
    ('', '1596473-1', CONVERT(datetime, '2002-12-17 08:39:00', 20))
;
Run Code Online (Sandbox Code Playgroud)

目前,我正在更新[E]在现场Mp通过对匹配表[M],其中的DTE字段(Mp)是certian范围(比如+ -3天)之内.目前执行此操作的查询

UPDATE [Mp] 
SET [E] = [Ep].[E] 
FROM [Mp] INNER JOIN [Ep] 
    ON [Mp].[M] = [Ep].[M] 
WHERE [Mp].[DTE] BETWEEN [Ep].[DTE] - 3 AND [Ep].[DTE] + 3;
Run Code Online (Sandbox Code Playgroud)

这将更新[Mp].[E][Mp].[M] = N'1596473-1'1596473-2.Essentailly SQL Server发现的第一个有效的条目.但是,我想更新此查询,以便SQL Server [M]在所需日期范围内(就像现在这样)匹配字段,但是对于[Ep].[DTE]最接近[Mp].[DTE]值的值2002-12-17 08:39:00.

我已经看过以DATEDIFF下面的方式添加一个子句

UPDATE [Mp] 
SET [E] = [Ep].[E] 
FROM [Mp] INNER JOIN [Ep] 
    ON [Mp].[M] = [Ep].[M] 
WHERE [Mp].[DTE] BETWEEN [Ep].[DTE] - 3 AND [Ep].[DTE] + 3 
ORDER BY DATEDIFF(minutes, [Mp].[DTE], [Ep].[DTE]);
Run Code Online (Sandbox Code Playgroud)

很明显我不能这样做,但我不确定如何对此进行修改以使其有效.更新后[Mp]的最终数据应该是

  1595861-1     1595861-1   2002-11-26 14:18:00.000 
  1595904-1     1595904-1   2002-11-24 15:15:00.000 
  1596298-1     1596298-1   2002-12-17 11:12:00.000 
  1596357-1     1596357-1   2002-12-09 19:57:00.000 
  1596369-1     1596369-1   2002-12-11 06:00:00.000 
  1596370-1     1596370-1   2002-12-19 12:31:00.000 
**1596473-5**   1596473-1   2002-12-17 08:39:00.000 
Run Code Online (Sandbox Code Playgroud)

谢谢你的时间.

Era*_*per 5

请首先检查CTE产生的数据作为输出

对于最近的数据,我根据DATEDIFF()函数提取的时差计算使用SQL ROW_NUMBER函数和Partition By子句.为了消除以前和以后的记录,我使用了ABS()数学函数.

select
*,
ROW_NUMBER() over (partition by [Mp].[M] order by abs(datediff(mi, [Mp].[DTE], [Ep].[DTE]))) as rn,
abs(datediff(mi, [Mp].[DTE], [Ep].[DTE])) diff
from Mp
left join Ep 
    on [Mp].[M] = [Ep].[M] 
WHERE [Mp].[DTE] BETWEEN dateadd(dd,-3,[Ep].[DTE]) AND dateadd(dd,3,[Ep].[DTE])
Run Code Online (Sandbox Code Playgroud)

然后在UPDATE命令中使用相同的CTE表达式,如下所示,可以将所需数据填充到目标数据库表中

;with cte as (
    select
        [Mp].[M] as M,
        [Ep].E as E,
    ROW_NUMBER() over (partition by [Mp].[M] order by abs(datediff(mi, [Mp].[DTE], [Ep].[DTE]))) as rn,
    abs(datediff(mi, [Mp].[DTE], [Ep].[DTE])) diff
    from Mp
    left join Ep 
        on [Mp].[M] = [Ep].[M] 
    WHERE [Mp].[DTE] BETWEEN dateadd(dd,-3,[Ep].[DTE]) AND dateadd(dd,3,[Ep].[DTE])
)
update [Mp]
set [E] = cte.E
from [Mp]
inner join cte on [Mp].M = cte.M and cte.rn = 1
where 
    cte.E is not null
Run Code Online (Sandbox Code Playgroud)

执行UPDATE语句后,目标表数据如下

在此输入图像描述

我希望这是你所需要的