[英]Convert Cursor to T-SQL
我有下面的光標完美地工作。 主要問題是運行需要一個多小時,這是一個問題。
誰能看到如何將其轉換為 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
這顯然是未經測試的。 您需要向我們提供一些示例數據才能使其完美。 但下面是一個開始。 除了為每個值增加 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;
當你談到性能時,我的第一個想法是確保你有一個關於 VisitTransitions.VisitId(當然還有 Visit.VisitId)的索引。 但是就沒有迭代的重寫而言,我想知道您是否考慮過以下兩個語句:
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;
如果除了 (1,2,3) 之外還有 AreaNames,這可能並不完全正確,但原則上我認為它會起作用並且您可以以此為基礎。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.