1

我有一张#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 分钟才能完成,日期间隔约为 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 .....截至 2014 年 01 01 5.50

4

3 回答 3

1

It is not entirely clear to me what you are trying to accomplish. Nevertheless, loops in SQL should be avoided if possible.

You might consider an UPDATE statement similar to:

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

followed by something that inserts records for the "missing" times. Without more information on the purpose of this code, it is difficult to provide more help.

于 2015-01-02T05:15:04.493 回答
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分钟endtimeProfileTrackTimeId

;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)

请让我知道任何更改。

于 2015-01-02T10:15:59.280 回答
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 语句来完成。

于 2015-01-02T11:28:43.683 回答