2015-01-02 22 views
1

我有一個表我正在循環的表#TrackPlayedInformation。的#TrackPlayedInformation樣本數據如下:SQL Server循環執行需要太多時間

ProfileTrackTimeId JukeBoxTrackId ProfileId EndTime     SessionId StartTime 
     14     52    33  2014-08-16 05:47:19.410 23424234 2014-08-16 05:45:19.410 
     15     51    33  2014-11-16 05:47:19.410 23424234 2014-08-16 05:45:19.410 

我循環通過#TrackPlayedInformation並分割的開始時間和結束時間上每分鐘之間的時間間隔。新的時間插在一個物理表TempGraph

TempGraph的結構是

TempGraphId AirTime     AirCount 
170390  2014-08-16 05:46:19.410  0 
170391  2014-08-16 05:47:19.410  0 

雖然插入到TempGraph如果不存在被檢查,如果存在,它更新由1 aircount遞增否則插入新的條目。

查詢執行大約需要20分鐘才能完成id,日期間隔約爲3個月。有沒有更快的方法來實現結果?

我鍛鍊的查詢如下:

USE [SocialMob] 
GO 
/****** Object: StoredProcedure [dbo].[pDeleteTempGraph] Script Date: 01/02/2015 09:00:32 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER PROCEDURE [dbo].[pDeleteTempGraph] 

AS 
BEGIN 
print('start') 
declare @UserId int 
declare @ProfileTrackTimeId int 
set @UserId=1048 
drop table #TrackPlayedInformation 
delete from TempGraph 
declare @loopCount int 
declare @StartTime datetime 
declare @LastDate datetime 
declare @tempCount int 
declare @EndTime datetime 
declare @SaveTime datetime 
declare @checkDate datetime 
declare @countCheck int 

--querying input-- 
--drop table #TrackPlayedInformation 
--declare @UserId int 
--set @UserId=33 
SELECT ProfileTrackTimeId,ProfileTrackTime.JukeBoxTrackId,ProfileId,EndTime,SessionId,StartTime into #TrackPlayedInformation 
FROM ProfileTrackTime LEFT JOIN 
(SELECT JukeBoxTrackId FROM JukeBoxTrack INNER JOIN 
Album ON JukeBoxTrack.AlbumId=Album.AlbumId WHERE [email protected]) as AllTrackId 
ON ProfileTrackTime.JukeBoxTrackId=AllTrackId.JukeBoxTrackId 


set @loopCount=0 
declare @count as int 
select @count=COUNT(ProfileTrackTimeId) from #TrackPlayedInformation 
set @LastDate=GETDATE()--storing current datetime 
print('looping starts') 
while @loopCount<@count 
begin 
    select @StartTime=StartTime from #TrackPlayedInformation 
    select @EndTime=EndTime from #TrackPlayedInformation 
    select @ProfileTrackTimeId=ProfileTrackTimeId from #TrackPlayedInformation 

    --select @checkDate=AirTime from TempGraph 
     while @StartTime<[email protected] 
     begin 
      set @StartTime=DATEADD(minute,1,@StartTime) 

      --checking for duplication 
      --SELECT @countCheck= count(TempGraphId) FROM TempGraph WHERE [email protected] 
      --select @countCheck 
      --if (@countCheck<1) 
      if not exists(select top 1 TempGraphId from TempGraph where [email protected]) 
      begin 
       --print('inserting') 
       insert TempGraph (AirTime,AirCount) values(@StartTime,0) 
      end 
      else 
      begin 
       --print('updating') 
       update TempGraph set AirCount=AirCount+1 where [email protected] 
      end 
      set @[email protected] 
     end 

     set @LastDate=DATEADD(MINUTE,1,@LastDate); 
    --deleting row from #TrackPlayedInformation 
     --print('deleting') 
     delete from #TrackPlayedInformation where [email protected] 
     set @[email protected]+1 --incrementing looping condition 
end 

begin 
    insert TempGraph (AirTime,AirCount) values(@LastDate,0) 
end 

begin 
    declare @nowdate datetime 
    set @nowdate=GETDATE() 
    insert TempGraph (AirTime,AirCount) values(@nowdate,0) 
end 

    select * from TempGraph; 
    delete from TempGraph; 
END 

我將嘗試分鐘分裂的時間間隔爲EG-考慮日期2014 01 01 5.40爲開始時間和2014年01 01 5.50爲結束再寄一次需要進入TempGraph 2014年01 01 5.41,2014 01 01 5.42,2014 01 01 5.43 ..... upto 2014 01 01 5.50

+0

最後兩個插入(即)'@ LastDate'和'@ nowdate'有什麼用處。 –

+0

- @ LastDate用於插入最後一個條目,並且 - @ nowdate用於在當前日期時間插入條目 – M14

+0

*我正在嘗試按分鐘將時間間隔拆分爲eg-考慮日期2014 01 01 5.40作爲開始時間和2014 01 01 5。50作爲結束時間*只需使用遞歸cte生成一個0到10之間的數字序列(分鐘),然後將'DATEADD'到他們的開始時間。 http://smehrozalam.wordpress.com/2009/06/09/t-sql-using-common-table-expressions-cte-to-generate-sequences/ –

回答

1

對我來說,你不完全清楚你想要完成什麼。儘管如此,儘可能避免SQL中的循環。

您可以考慮類似於UPDATE聲明:

UPDATE TempGraph 
SET AirCount = AirCount + 1 
WHERE AirTime BETWEEN @StartTime AND @EndTime 

其次是一些插入記錄「丟失」的時代。如果沒有關於此代碼目的的更多信息,則很難提供更多幫助。

+0

我想分割一個時間間隔分鐘爲eg-考慮日期2014 01 01 5.40作爲開始時間和2014 01 01 5.50作爲結束時間.i需要在TempGraph中錄入爲2014 01 01 5.41,2014 01 01 5.42,2014 01 01 5.43 ..... upto 2014 01 01 5.50 – M14

1

我真的不明白你在做什麼。以下信息可能有助於您

SELECT * INTO #TEMP 
FROM 
(
SELECT 14 ProfileTrackTimeId,'2014-08-16 05:47:19.410' StartTime, '2014-08-16 05:50:19.410' EndTime 
UNION ALL 
SELECT 14 ProfileTrackTimeId,'2014-08-16 10:20:19.410' StartTime, '2014-08-16 10:23:19.410' EndTime 
UNION ALL 
SELECT 20 ProfileTrackTimeId,'2014-08-17 08:10:19.410' StartTime, '2014-08-17 08:12:19.410' EndTime 
UNION ALL 
SELECT 20 ProfileTrackTimeId,'2014-08-18 13:59:19.410' StartTime, '2014-08-18 14:02:19.410' EndTime 
)TAB 

現在你會得到每一個日期分鐘starttimeendtime之間,每ProfileTrackTimeId

;WITH CTE AS 
(
    SELECT ProfileTrackTimeId,CAST(StartTime AS DATETIME) FDATES, 
    CAST(EndTime AS DATETIME) TDATES 
    FROM #TEMP 
    UNION ALL 
    SELECT T.ProfileTrackTimeId,DATEADD(MINUTE,1,FDATES),TDATES 
    FROM #TEMP T 
    JOIN CTE ON CTE.ProfileTrackTimeId = T.ProfileTrackTimeId 
    WHERE FDATES < TDATES 
) 
SELECT DISTINCT ProfileTrackTimeId,FDATES 
FROM CTE 
ORDER BY ProfileTrackTimeId,FDATES 
OPTION (MaxRecursion 0) 

請讓我知道的任何變化。

+1

+一個遞歸CTE,儘管你可能想在某處設置MAXRECURSION。 –

+0

感謝ta.speot.is。如果忘了給。將更新@ ta.speot.is –

0

要在startTime和EndTime之間創建序列,您可以使用nodes()方法的模式。要執行插入和更新操作,您可以使用MERGE語句。以下示例顯示如何執行此操作。

ALTER PROC [dbo].[pDeleteTempGraph] 
AS 
BEGIN 

    IF OBJECT_ID('tempdb..#seq') IS NOT NULL DROP TABLE #seq 
    CREATE TABLE #seq(AirTime datetime, AirCount int) 

    ;WITH cte AS 
    (
    SELECT *, CAST(REPLICATE(CAST('<M></M>' AS varchar(MAX)),ISNULL(DATEDIFF(MINUTE, StartTime, EndTime), 1)) AS xml) AS xmlCol 
    FROM #TrackPlayedInformation t1 
    ),cte2 AS 
    ( 
    SELECT DATEADD(MINUTE, ROW_NUMBER() OVER(PARTITION BY profileTrackTimeId ORDER BY StartTime), StartTime) AS AirTime 
    FROM cte CROSS APPLY xmlCol.nodes ('/M') AS Split(M) 
    ) 
    INSERT #seq 
    SELECT AirTime, COUNT(*) AS AirCount 
    FROM cte2 
    GROUP BY AirTime 

    MERGE TempGraph AS TARGET 
    USING (   
      SELECT AirTime, AirCount 
      FROM #seq   
      ) AS SOURCE ON TARGET.AirTime = SOURCE.AirTime 
    WHEN MATCHED THEN UPDATE SET AirCount = TARGET.AirCount + SOURCE.AirCount 
    WHEN NOT MATCHED BY TARGET THEN 
    INSERT(AirTime, AirCount) 
    VALUES(SOURCE.AirTime, SOURCE.AirCount); 

    SELECT * 
    FROM TempGraph 

    DELETE FROM TempGraph 

END 

但是也許MERGE語句在你的特定情況下是過度的,並且足夠表#seq。無論如何,如果你有一個額外的UPSERT邏輯,最好用MERGE語句來完成。

+1

這是一個很好的答案:) @Alexander Fedorenko –