2015-01-02 23 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 –