2015-01-02 3 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, если не существует проверяется, если существует, то он обновляет 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 [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 в конец time.i необходимо ввести в TempGraph как 2014 01 01 5.41, 2014 01 01 5.42, 2014 01 01 5.43 ..... до 2014 01 01 5.50

+0

что использовать последние две вставки (т.е.) '@ LastDate' и' @ nowdate'. –

+0

the - @ LastDate используется для вставки последней записи и - @ nowdate используется для вставки записи в текущее время datetime – M14

+0

* Я пытаюсь разделить интервал времени на минуту, например, на дату рассмотрения 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 в качестве конечного времени. Мне нужно ввести в TempGraph как 2014 01 01 5.41, 2014 01 01 5.42, 2014 01 01 5.43 ..... до 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 

Теперь вы получите каждую дату с минутой между 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) 

Пожалуйста, дайте мне знать, для каких-либо изменений.

+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

Это хороший ответ :) @ Александр Федоренко –

Смежные вопросы