简体   繁体   English

将游标转换为 T-SQL

[英]Convert Cursor to T-SQL

I've got the below cursor that works perfectly.我有下面的光标完美地工作。 The main issue is that it takes over an hour to run which is a problem.主要问题是运行需要一个多小时,这是一个问题。

Can anyone see how it could be converted to a T-SQL statement?谁能看到如何将其转换为 T-SQL 语句?

DECLARE @VisitID int
DECLARE @PreviousVisitID int
DECLARE @VisitTimeIn datetime
DECLARE @Area1TimeIn datetime
DECLARE @Area1TimeOut datetime
DECLARE @Area2TimeIn datetime
DECLARE @Area2TimeOut datetime
DECLARE @Area3TimeIn datetime
DECLARE @Area3TimeOut datetime

DECLARE db_cursor CURSOR FOR 
select distinct VisitID from #temp

OPEN db_cursor  
FETCH NEXT FROM db_cursor INTO @VisitID  

WHILE @@FETCH_STATUS = 0  
BEGIN  

    select @VisitTimeIn = TimeIn from Visit where VisitID = @VisitID

    select @Area1TimeIn = @VisitTimeIn
    select @Area1TimeOut = DateAdd(ss,500,@Area1TimeIn)
    select @Area2TimeIn = @Area1TimeOut
    select @Area2TimeOut = DateAdd(ss,500,@Area2TimeIn)
    select @Area3TimeIn = @Area2TimeOut
    select @Area3TimeOut = DateAdd(ss,500,@Area3TimeIn)

    Update VisitTransitions Set TimeIn = @Area1TimeIn where VisitID = @VisitID and AreaName = '1'
    Update VisitTransitions Set TimeOut = @Area1TimeOut where VisitID = @VisitID and AreaName = '1'
    Update VisitTransitions Set TimeIn = @Area2TimeIn where VisitID = @VisitID and AreaName = '2'
    Update VisitTransitions Set TimeOut = @Area2TimeOut where VisitID = @VisitID and AreaName = '2'
    Update VisitTransitions Set TimeIn = @Area3TimeIn where VisitID = @VisitID and AreaName = '3'
    Update VisitTransitions Set TimeOut = @Area3TimeOut where VisitID = @VisitID and AreaName = '3'

    Update Visit Set TimeOut = @Area3TimeOut where VisitID = @VisitID

    FETCH NEXT FROM db_cursor INTO @VisitID 
END 

CLOSE db_cursor  
DEALLOCATE db_cursor 

This is untested obviously.这显然是未经测试的。 You'd need to provide us some sample data in order to make it perfect.您需要向我们提供一些示例数据才能使其完美。 But the below is a start.但下面是一个开始。 It doesn't appear that you're doing anything special with the time in and time out values apart from adding 500 seconds to each one, so:除了为每个值增加 500 秒之外,您似乎没有对时间值和超时值做任何特别的事情,所以:

BEGIN TRAN;

UPDATE vt
SET vt.TimeIn = v.TimeIn,
vt.TimeOut = DateAdd(ss,500,v.TimeIn)
FROM dbo.VisitTransitions vt
INNER JOIN #tmp t ON t.VisitId = vt.VisitId
INNER JOIN dbo.Visit v ON v.VisitID = vt.VisitID
AND AreaName = '1';

UPDATE vt
SET vt.TimeIn = DateAdd(ss,500,v.TimeIn),
vt.TimeOut = DateAdd(ss,1000,v.TimeIn)
FROM dbo.VisitTransitions vt
INNER JOIN #tmp t ON t.VisitId = vt.VisitId
INNER JOIN dbo.Visit v ON v.VisitID = vt.VisitID
AND AreaName = '2';

UPDATE vt
SET vt.TimeIn = DateAdd(ss,1000,v.TimeIn),
vt.TimeOut = DateAdd(ss,1500,v.TimeIn)
FROM dbo.VisitTransitions vt
INNER JOIN #tmp t ON t.VisitId = vt.VisitId
INNER JOIN dbo.Visit v ON v.VisitID = vt.VisitID
AND AreaName = '3';

UPDATE v
SET v.TimeOut = DateAdd(ss,1500,v.TimeIn)
FROM Visit v
INNER JOIN #tmp t ON t.VisitId = v.VisitId;

--COMMIT TRAN;
--ROLLBACK TRAN;

My first thought when you talk about the performance is to ensure you have an index on VisitTransitions.VisitId (and Visit.VisitId of course).当你谈到性能时,我的第一个想法是确保你有一个关于 VisitTransitions.VisitId(当然还有 Visit.VisitId)的索引。 But in terms of rewriting without the iterations, I wonder if you've considered something like the following two statements:但是就没有迭代的重写而言,我想知道您是否考虑过以下两个语句:

UPDATE vt
SET 
 vt.TimeIn = CASE WHEN vt.AreaName = '1' THEN v.TimeIn WHEN vt.AreaName = '2' THEN DateAdd(ss, 500, v.TimeIn) ELSE DateAdd(ss, 1000, v.TimeIn) END,
 vt.TimeOut = CASE WHEN vt.AreaName = '1' THEN DateAdd(ss, 500, v.TimeIn) WHEN vt.AreaName = '2' THEN DateAdd(ss, 1000, v.TimeIn) ELSE DateAdd(ss, 1500, v.TimeIn) END
FROM VisitTransitions vt 
 INNER JOIN Visit v
  ON v.VisitID = vt.VisitID
 INNER JOIN #temp t
  ON v.VisitID = t.VisitID;

UPDATE v
SET 
  v.TimeOut = DateAdd(ss, 1500, v.TimeIn)
FROM Visit v
  ON v.VisitID = vt.VisitID
INNER JOIN #temp t
  ON v.VisitID = t.VisitID;

This might not be exactly right if you have AreaNames besides (1,2,3), but in principle I think it will work and you could build off of it.如果除了 (1,2,3) 之外还有 AreaNames,这可能并不完全正确,但原则上我认为它会起作用并且您可以以此为基础。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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