我有两个表跟踪不同系统中的项目,为简单起见,我们称之为Alpha和Beta系统。我试图将两个表合并为一个表,可以正确跟踪项的位置。
跟踪的项目以Alpha开头,可以进入Beta版。但是,由于系统未连接,因此输入Beta的开始时间并不总是与Alpha中的结束时间匹配。
正确跟踪的示例项目如下
System---ID----Item------- Start---------------- End
Alpha - 987 - 123 - 20/5/2015 07:00:00 - 20/5/2015 08:00:00
Alpha - 374 - 123 - 20/5/2015 08:00:00 - 20/5/2015 09:00:00
Beta - 184 - 123 - 20/5/2015 09:00:00 - 20/5/2015 10:00:00
Beta - 798 - 123 - 20/5/2015 10:00:00 - 20/5/2015 12:00:00
我的问题是因为系统没有链接,我的情况是项目同时出现在Alpha和Beta中。如下
System---ID----Item------- Start---------------- End
Alpha - 987 - 123 - 20/5/2015 07:00:00 - 20/5/2015 08:00:00
Beta - 184 - 123 - 20/5/2015 07:30:00 - 20/5/2015 10:00:00
Alpha - 374 - 123 - 20/5/2015 08:00:00 - 20/5/2015 09:00:00
Beta - 798 - 123 - 20/5/2015 10:00:00 - 20/5/2015 12:00:00
Alpha是更好的系统,应始终值得信任。
所以我在上述情况下的预期结果是修改记录184并将其开始时间改为记录374的结束时间。
还有另一个案例应该被考虑,以及Alpha记录在最后一个Beta记录开始之前开始和结束的位置。
有意义吗?我希望如此,过去几天它让我疯了。
感谢您提供任何帮助。
答案 0 :(得分:0)
如果您使用SQL Server 2012及更高版本(感谢提示Karl),您可以使用LAG和LEAD,如下所示:
查询1 :
select [System], [ID], [Item],
[Start],
CASE WHEN LAG([End]) OVER(ORDER BY [Start]) > [Start] AND
LAG([System]) OVER(ORDER BY [Start]) = 'Alpha' AND
[System] = 'Beta'
THEN LAG([End]) OVER(ORDER BY [Start]) ELSE [Start] END As [CorrectStart],
[End],
CASE WHEN LEAD([Start]) OVER(ORDER BY [Start]) < [End] AND
LEAD([System]) OVER(ORDER BY [Start]) = 'Alpha' AND
[System] = 'Beta'
THEN LEAD([Start]) OVER(ORDER BY [Start]) ELSE [End] END As [CorrectEnd]
FROM Table1
order by [Start]
<强> Results 强>:
| System | ID | Item | Start | CorrectStart | End | CorrectEnd |
|--------|-----|------|-----------------------|-----------------------|-----------------------|-----------------------|
| Alpha | 987 | 123 | May, 20 2015 07:00:00 | May, 20 2015 07:00:00 | May, 20 2015 08:00:00 | May, 20 2015 08:00:00 |
| Beta | 374 | 123 | May, 20 2015 07:30:00 | May, 20 2015 08:00:00 | May, 20 2015 10:00:00 | May, 20 2015 09:00:00 |
| Alpha | 184 | 123 | May, 20 2015 09:00:00 | May, 20 2015 09:00:00 | May, 20 2015 10:00:00 | May, 20 2015 10:00:00 |
| Beta | 798 | 123 | May, 20 2015 10:00:00 | May, 20 2015 10:00:00 | May, 20 2015 12:00:00 | May, 20 2015 12:00:00 |
答案 1 :(得分:0)
我想你想找到每个项目的最后一个alpha和第一个beta,并用最后一个alpha的结束时间更新第一个beta开始时间。
这可以简化,当然也会针对性能进行优化。我这样离开了,因为它非常明确。
注意:LAG和LEAD是在SQL Server 2012中引入的,因此如果你有这个或更晚的话,那么cha的解决方案肯定会有效。
--create the sample data
DECLARE @Tracking TABLE(Name VARCHAR(10),ID INT,Item INT,StartTime DATETIME2,EndTime DATETIME2)
INSERT INTO @Tracking
SELECT * FROM (VALUES
('Alpha' , 987 , 123 , '2015-05-20 07:00:00' , '2015-05-20 08:00:00')
,('Beta' , 184 , 123 , '2015-05-20 07:30:00' , '2015-05-20 10:00:00')
,('Alpha' , 374 , 123 , '2015-05-20 08:00:00' , '2015-05-20 09:00:00')
,('Beta' , 798 , 123 , '2015-05-20 10:00:00' , '2015-05-20 12:00:00')
) AS tbl(Name,ID,Item,StartTime,EndTime)
--get row number for the sample data over sytem name and item
--use a cte for clarity
;WITH
cte AS (
SELECT Name,ID,Item,StartTime,EndTime
,rn = ROW_NUMBER() OVER (PARTITION BY Item,Name ORDER BY StartTime)
,rn_reverse = ROW_NUMBER() OVER (PARTITION BY Item,Name ORDER BY StartTime DESC)
FROM @Tracking
),
--get only the last alpha
LastAlphas AS (
SELECT * FROM cte WHERE Name = 'Alpha' AND rn_reverse = 1
),
--and the forst beta
FirstBetas AS (
SELECT * FROM cte WHERE Name = 'Beta' AND rn = 1
)
--join them all and do the update
UPDATE @Tracking
SET StartTime = a.EndTime
FROM @Tracking t
JOIN FirstBetas b ON t.id = b.id
JOIN LastAlphas a ON t.item = a.item
SELECT * FROM @Tracking ORDER BY Name, StartTime
--Alpha 987 123 2015-05-20 07:00:00.0000000 2015-05-20 08:00:00.0000000
--Alpha 374 123 2015-05-20 08:00:00.0000000 2015-05-20 09:00:00.0000000
--Beta 184 123 2015-05-20 09:00:00.0000000 2015-05-20 10:00:00.0000000
--Beta 798 123 2015-05-20 10:00:00.0000000 2015-05-20 12:00:00.0000000
答案 2 :(得分:0)
我们可以通过简单地在下面提到的查询中连接两个表来实现这一点: -
with cte1 as
(
select *,ROW_NUMBER() over (partition by name order by starttime) as rn
from #a
),cte2 as
(
select a.name,a.id,a.item,min(isnull((case when a.name = 'Beta' then b.endtime else a.starttime end),a.starttime)) as starttime,a.endtime
from cte1 as a
left join cte1 as b
on b.rn = a.rn + 1
group by a.name,a.id,a.item,a.endtime
)
update a
set a.starttime = b.starttime,
a.endtime = b.endtime
from #a as a
inner join cte2 as b
on b.id = a.id