根据表1中的日期,使用表2中的记录更新表1中的记录

时间:2016-05-25 15:41:14

标签: sql sql-server sql-server-2008

我是网站的新手,我希望你能帮忙...

我正试图根据LegNumberTable 2之间Table 1的{​​{1}}标记来自datetime的{​​{1}}。来自Table1的记录。

在我的示例中,datetime中日期时间介于Table 2Table 1之间的记录应标有4/5/16 4:02 AM 4/7/16 6:53 AM(来自{{ 1}}基于LegNumber通过1862410 Table 2)。希望我没有让这个问题过于混乱。

enter image description here

3 个答案:

答案 0 :(得分:1)

首先我们创建cte并收集时间间隔,然后选择显示输出:

;WITH LegsRowNumbers AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY LegStartDate ASC) as rn
FROM Table2 t2
), GetLegsIntervals AS (
SELECT  l1.Tractor,
        --Here may be another format, check CAST and CONVERT article on MSDN
        CONVERT(datetime,l1.LegStartDate, 120) as LegStartDate, 
        DATEADD(minute,-1,l2.LegStartDate) as LegEndDate,
        l1.LegNumber
FROM LegsRowNumbers l1
LEFT JOIN LegsRowNumbers l2
    ON l2.rn = l1.rn+1
)

SELECT  t.Tractor,
        t.TollExitDateTime,
        g.LegNumber
FROM Table1 t
LEFT JOIN GetLegsIntervals g
    ON t.TollExitDateTime between g.LegStartDate and g.LegEndDate

输出:

Tractor TollExitDateTime    LegNumber
1404    2016-04-03 05:21 AM NULL
1404    2016-04-03 05:34 AM NULL
1404    2016-04-03 06:28 AM NULL
1404    2016-04-03 02:36 PM NULL
1404    2016-04-03 03:13 PM NULL
1404    2016-04-03 03:29 PM NULL
1404    2016-04-05 08:14 AM 1862410
1404    2016-04-05 08:26 AM 1862410
1404    2016-04-05 09:26 AM 1862410
1404    2016-04-05 03:15 PM 1862410
1404    2016-04-05 03:53 PM 1862410
1404    2016-04-05 04:09 PM 1862410

您可以将上次查询更改为UPDATE:

UPDATE t
SET LegNumber = g.LegNumber
FROM Table1 t
LEFT JOIN GetLegsIntervals g
    ON t.TollExitDateTime between g.LegStartDate and g.LegEndDate

答案 1 :(得分:0)

如果您是一个SQL Server 2012+,可以使用LEAD为每个设置LegEndDate

create table TABLE1(TRACTOR integer, TOLLEXITDATETIME datetime);
create table TABLE2(TRACTOR integer, LEGSTARTDATE datetime, LEGNUMBER integer);

insert into TABLE1
    select '1404',   '4/3/2016 5:21:00 AM' union all
    select '1404',   '4/5/2016 5:21:00 AM' union all
    select '1404',   '4/6/2016 5:21:00 AM' 
;

insert into TABLE2
    select '1404',   '4/4/2016 3:54:00 AM', 1862405  union all
    select '1404',   '4/5/2016 4:02:00 AM', 1862410 union all
    select '1404',   '4/7/2016 6:53:00 AM', 1865901
;


with TEMP_TABLE2(TRACTOR, LEGSTARTDATE, LEGENDDATE, LEGNUMBER)
AS(
    select 
      TRACTOR, 
      LEGSTARTDATE, 
      lead(LEGSTARTDATE) over (partition by TRACTOR order by LEGSTARTDATE) LEGENDDATE,
      LEGNUMBER
    from TABLE2
   )

select
    t1.TRACTOR,
    t1.TOLLEXITDATETIME,
    t2.LEGNUMBER
from TABLE1 t1
left outer join TEMP_TABLE2 t2
on t1.TRACTOR = t2.TRACTOR
and t1.TOLLEXITDATETIME between t2.LEGSTARTDATE and coalesce(t2.LEGENDDATE, '12/31/9999')

答案 2 :(得分:0)

谢谢mo2的入门表代码:) 谢谢gofr1 ROW_NUMBER() OVER (ORDER BY LegStartDate ASC) as rn因为即使我一直使用它,我也完全消隐了。

表I用于测试

create table Table2(Tractor integer, LegStartDate datetime, LegNumber integer primary key);
create table Table1(Tractor integer, TollExitDateTime datetime, LegNumber     integer FOREIGN KEY REFERENCES Table2(Legnumber));

insert into TABLE1
select '1404',   '4/3/2016 5:21:00 AM', NULL union all
select '1404',   '4/3/2016 5:34:00 AM', NULL union all
select '1404',   '4/3/2016 6:28:00 AM', NULL union all
select '1404',   '4/3/2016 2:36:00 PM', NULL union all
select '1404',   '4/3/2016 3:13:00 PM', NULL union all
select '1404',   '4/3/2016 3:29:00 PM', NULL union all
select '1404',   '4/5/2016 8:14:00 AM', NULL union all
select '1404',   '4/5/2016 8:26:00 AM', NULL union all
select '1404',   '4/5/2016 9:26:00 AM', NULL union all
select '1404',   '4/5/2016 3:15:00 PM', NULL union all
select '1404',   '4/5/2016 3:53:00 PM', NULL union all
select '1404',   '4/5/2016 4:09:00 PM', NULL
;

insert into TABLE2
select '5000',   '4/4/2016 3:54:00 AM', 5555555 union all --testing purpose
select '1404',   '4/3/2016 5:21:00 AM', 8888888 union all --testing purpose

select '1404',   '4/4/2016 3:54:00 AM', 1862405 union all
select '1404',   '4/5/2016 4:02:00 AM', 1862410 union all
select '1404',   '4/7/2016 6:53:00 AM', 1865901
;

这是我用来显示,更新,然后再次显示以进行测试的代码。

--This will just display what leg number goes with what
--I will probably be yelled at for not using joins.  Normally I do but it worked perfectly fine in this situation to not so I did not bother to.
;WITH LegRows AS (SELECT *, ROW_NUMBER() OVER (ORDER BY t2a.LegStartDate ASC) as rn FROM Table2 t2a)
SELECT t1a.Tractor, t1a.TollExitDateTime, t1a.LegNumber, r1.LegStartDate, r1.LegNumber FROM Table1 t1a, LegRows r1, LegRows r2 WHERE t1a.TollExitDateTime BETWEEN r1.LegStartDate AND r2.LegStartDate AND r1.rn+1 = r2.rn

--This updates the leg information
;WITH LegRows AS (SELECT *, ROW_NUMBER() OVER (ORDER BY t2a.LegStartDate ASC) as rn FROM Table2 t2a)
UPDATE Table1 Set LegNumber = r1.LegNumber FROM Table1 t1a, LegRows r1, LegRows r2 WHERE t1a.TollExitDateTime BETWEEN r1.LegStartDate AND r2.LegStartDate AND r1.rn+1 = r2.rn

--This again displays what leg number goes with what to confirm the update
;WITH LegRows AS (SELECT *, ROW_NUMBER() OVER (ORDER BY t2a.LegStartDate ASC) as rn FROM Table2 t2a)
SELECT t1a.Tractor, t1a.TollExitDateTime, t1a.LegNumber, r1.LegStartDate, r1.LegNumber FROM Table1 t1a, LegRows r1, LegRows r2 WHERE t1a.TollExitDateTime BETWEEN r1.LegStartDate AND r2.LegStartDate AND r1.rn+1 = r2.rn

Output that I got.