我有一个表#TrackPlayedInformation
,我正在循环。 #TrackPlayedInformation
的示例数据如下:
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
(如果不存在),如果存在,则更新aircount,加1,否则作为新条目插入。
查询执行大约需要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 Album.UserId=@UserId) 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<=@EndTime
begin
set @StartTime=DATEADD(minute,1,@StartTime)
--checking for duplication
--SELECT @countCheck= count(TempGraphId) FROM TempGraph WHERE AirTime=@StartTime
--select @countCheck
--if (@countCheck<1)
if not exists(select top 1 TempGraphId from TempGraph where AirTime=@StartTime)
begin
--print('inserting')
insert TempGraph (AirTime,AirCount) values(@StartTime,0)
end
else
begin
--print('updating')
update TempGraph set AirCount=AirCount+1 where AirTime=@StartTime
end
set @LastDate=@StartTime
end
set @LastDate=DATEADD(MINUTE,1,@LastDate);
--deleting row from #TrackPlayedInformation
--print('deleting')
delete from #TrackPlayedInformation where ProfileTrackTimeId=@ProfileTrackTimeId
set @loopCount=@loopCount+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
我试图将时间间隔除以分钟,例如考虑日期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 :(得分:1)
我并不完全清楚你想要完成什么。尽管如此,应尽可能避免SQL中的循环。
您可以考虑UPDATE
语句类似于:
UPDATE TempGraph
SET AirCount = AirCount + 1
WHERE AirTime BETWEEN @StartTime AND @EndTime
后面跟着&#34;缺少&#34;的记录。倍。如果没有关于此代码目的的更多信息,则很难提供更多帮助。
答案 1 :(得分: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
现在,对于每starttime
endtime
和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)
如有任何改变,请通知我。
答案 2 :(得分: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语句来做。