简体   繁体   中英

Update a record in table 1 with a record from table 2 based on a date in table 1

I'm new to the site, and I'm hoping you can help...

I'm trying to stamp the LegNumber from Table 2 into Table 1 based on the datetime of the record in Table1 falling between the datetime of the record(s) from Table 2 .

In my example, the records in Table 1 with a datetime that falls between 4/5/16 4:02 AM and 4/7/16 6:53 AM should be stamped with LegNumber 1862410 (from Table 2) based on the datetimes of 4/5/16 8:14 AM thru 4/5/16 4:09 PM . Hopefully, I haven't made this inquiry too confusing.

在此处输入图片说明

At first we create to cte's and gather time intervals, then select to show output:

;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

Output:

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

You can change last query to UPDATE:

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

If you are one SQL Server 2012+, you can use the LEAD to set the LegEndDate for each:

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')

Thank you mo2 for starter table code :) And thank you gofr1 for the ROW_NUMBER() OVER (ORDER BY LegStartDate ASC) as rn because even though I use it all the time I completely blanked it.

Table I used for testing

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 is the code I used to display, update, then display again for testing.

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

我得到的输出。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM