2017-02-17 31 views
-1

Это код SQL, который проходит через таблицу, содержащую различные записи с начальными и конечными данными, такими как медленно изменяющееся измерение. При проверке измерения мы выяснили, что иногда дата начала не соответствует дате окончания. Таким образом, мы зацикливаем таблицу и воссоздаем даты начала и окончания, чтобы убедиться, что дата начала/окончания на самом деле равна min/max доступных дат. Но процесс занимает слишком много времени, чтобы работать через 9 миллионов строк. Я хотел бы использовать цикл while, но не могу понять, чтобы сохранить значение min/max и определить переключатель в ID.Может кто-нибудь помочь мне с заменой курсора в следующем SQL-коде.

DECLARE @MINDDEB Datetime 
DECLARE @DDEB Datetime 
DECLARE @DFIN Datetime 
DECLARE @CECV float 
DECLARE @AIDNEBHNPRPEP int 
DECLARE @CETA float 
DECLARE @AIDNEBHNPRAFI int 
DECLARE @MAXDFIN Datetime 
DECLARE @OLDCECV float 
DECLARE @OLDAIDNEBHNPRPEP int 
DECLARE @OLDCETA float 
DECLARE @OLDAIDNEBHNPRAFI int 

SET @MINDDEB=9999-12-31 
SET @MAXDFIN=1835-12-31 
drop table dbo.TBYDWHTEBHNPRAFIVRS_CURSORTABLE 
--T2 
SELECT DDEB, DFIN, CETA,AIDNEBHNPRAFI 
into dbo.TBYDWHTEBHNPRAFIVRS_CURSORTABLE 
FROM dbo.TBYDWHTEBHNPRAFIVRS 
WHERE AIDNEBHNPRAFI=-1 
ORDER BY AIDNEBHNPRAFI,DDEB 

DECLARE T2_CURSOR CURSOR FOR 
select DDEB, DFIN, CETA,AIDNEBHNPRAFI 
from TBYDWHTEBHNPRAFIVRS 
where DFIN>DDEB and BRRDDEL<>1 and CSTUVRS = 1 --and AIDNEBHNPRAFI in (1080,1033143,2311904) 
order by AIDNEBHNPRAFI,DDEB,CETA,CECV 


OPEN T2_CURSOR 

FETCH NEXT FROM T2_CURSOR 
INTO @DDEB, @DFIN, @CETA,@AIDNEBHNPRAFI 
SET @[email protected] 
SET @[email protected] 
--SET @[email protected] 

WHILE @@FETCH_STATUS = 0 
BEGIN 

    if (@[email protected] and @[email protected]) 
    BEGIN 
     --print 'entering first if' 
     IF (@MINDDEB>@DDEB) 
     BEGIN 
      SET @[email protected] 
     END 
     IF (@MAXDFIN<@DFIN) 
     BEGIN  
      SET @[email protected] 
     END 
    END 
    --print ' OLD CECV '+convert(varchar(10),@OLDCECV) +' new CECV '+ convert(varchar(10),@CECV) +' OLDAID '+ convert(varchar(10),@OLDAIDNEBHNPRPEP) +' NEWAID '+ convert(varchar(10),@AIDNEBHNPRPEP) 
    -- +' NEWDDEB '+ convert(varchar(10),@DDEB,101) +' MINDDEB '+ convert(varchar(10),@MINDDEB,101) +' NEWDFIn '+ convert(varchar(10),@DFIN,101) +' MAXDFIN '+ convert(varchar(10),@MAXDFIN,101) 



FETCH NEXT FROM T2_CURSOR 
    INTO @DDEB, @DFIN, @CETA,@AIDNEBHNPRAFI 

    if (@OLDCETA<>@CETA or @OLDAIDNEBHNPRAFI<>@AIDNEBHNPRAFI) 
    BEGIN 
     INSERT INTO TBYDWHTEBHNPRAFIVRS_CURSORTABLE (DDEB, DFIN, CETA,AIDNEBHNPRAFI) 
     VALUES (@MINDDEB,@MAXDFIN,@OLDCETA,@OLDAIDNEBHNPRAFI) 
     SET @[email protected] 
     --SET @[email protected] 
     SET @[email protected] 
     SET @[email protected] 
     SET @[email protected] 
    END 


END 
INSERT INTO TBYDWHTEBHNPRAFIVRS_CURSORTABLE (DDEB, DFIN, CETA,AIDNEBHNPRAFI) 
     VALUES (@MINDDEB,@MAXDFIN,@OLDCETA,@OLDAIDNEBHNPRAFI) 
CLOSE T2_CURSOR; 
DEALLOCATE T2_CURSOR; 

Это исходные данные
DDEB DFIN CETA AIDNEBHNPRAFI
2006-03-01 00: 00: 00,000 2006-04-30 23: 59: 59,000 1 +231272
2006-05-01 00 : 00: 00.000 2006-11-30 23: 59: 59 000 1 231272
2006-12-01 00: 00: 00.000 2007-04-30 23: 59: 59.000 1 231272
2007-05-01 00:00 : 00.000 2008-04-30 23: 59: 59 000 1 231272
2008-05-01 00: 00: 00.000 2008-08-31 23: 59: 59.000 1 231272
2008-09-01 00:00:00 , 000 2008-10-31 23: 59: 59 000 2 231272
2008-11-01 00: 00: 00.000 2009-04-30 23: 59: 59.000 1 231272
2009-05-01 00: 00: 00.000 2010 -01-31 23: 59: 59,000 1 231272
2010-02-01 00: 00: 00,000 9999-12-31 23: 59: 59.000 14 231272

и это результат, который мы получаем с помощью курсора

DDEB DFIN СЕТА AIDNEBHNPRAFI
2006-03-01 00: 00: 00,000 2008-08-31 23: 59: 59,000 1 231272
2008-09-01 00: 00: 00,000 2008-10-31 23: 59: 59 000 2 231272
2008-11-01 00: 00: 00.000 2010-01-31 23: 59: 59 000 1 231272
2010-02-01 00: 00: 00.000 9999-12-31 23: 59: 59.000 14 231272

+2

Либо упростите и минимизируйте вопрос, либо наймите кого-нибудь. – jarlh

+0

@jarlh, ваш комментарий выглядит как реклама для меня, как вы говорите * или нанимаете кого-то * ... :) – Rahul

+0

@Rahul, но я не тот кто-то. – jarlh

ответ

0

Попытка. Результаты возвращаются в соответствие, но вы захотите проверить его с большим количеством данных. Я также сделал предположения о типах данных. Если у вас разные, вам нужно будет обновить их соответствующим образом. CTE идентифицируют интервалы, которые не имеют последовательного партнера (разное 1 секунда между остановкой и следующим запуском) для времени начала и остановки. Затем он присваивает номерам последовательностей этим моментам и соединяет старт & времени остановки на основе последовательности.

Подробно, время начала 3/1/2006 не имеет непосредственно предшествующего времени остановки, поэтому оно включено и является первой стартовой последовательностью для своей группы. 11/1/2008 соответствует тем же критериям и является следующей стартовой последовательностью для своей группы. 8/31/2008 - это первое время остановки, которое не имеет начального времени начала и является первой последовательностью остановки для своей группы. Начиная с 3/1/2006 & 8/31/2008 являются первой последовательностью в своей группе, они отмечают начало и остановку для первого непрерывного интервала для группы.

IF OBJECT_ID('tempdb..#temp') IS NOT NULL 
    DROP TABLE #temp; 
GO 

CREATE TABLE #temp (
        DDEB DATETIME, 
        DFIN DATETIME, 
        CETA INT, 
        AIDNEBHNPRAFI INT 
        ); 

INSERT INTO #temp 
VALUES ('2006-03-01 00:00:00.000', '2006-04-30 23:59:59.000', '1', '231272'), 
(' 2006-05-01 00:00:00.000', '2006-11-30 23:59:59.000', '1', '231272'), 
(' 2006-12-01 00:00:00.000', '2007-04-30 23:59:59.000', '1', '231272'), 
(' 2007-05-01 00:00:00.000', '2008-04-30 23:59:59.000', '1', '231272'), 
(' 2008-05-01 00:00:00.000', '2008-08-31 23:59:59.000', '1', '231272'), 
(' 2008-09-01 00:00:00.000', '2008-10-31 23:59:59.000', '2', '231272'), 
(' 2008-11-01 00:00:00.000', '2009-04-30 23:59:59.000', '1', '231272'), 
(' 2009-05-01 00:00:00.000', '2010-01-31 23:59:59.000', '1', '231272'), 
(' 2010-02-01 00:00:00.000', '9999-12-31 23:59:59.000', '14', '231272'); 
WITH Starts AS (
SELECT *, RowSeq = ROW_NUMBER() OVER(PARTITION BY ceta, t.AIDNEBHNPRAFI ORDER BY ddeb) 
FROM #temp AS t 
WHERE NOT EXISTS (SELECT 1 
        FROM #temp AS It 
        WHERE t.CETA = It.CETA 
          AND t.AIDNEBHNPRAFI = It.AIDNEBHNPRAFI 
          AND It.DFIN = DATEADD(SECOND, -1, t.DDEB) 
        ) 
), Finishes AS (

SELECT *, RowSeq = ROW_NUMBER() OVER(PARTITION BY ceta, t.AIDNEBHNPRAFI ORDER BY dfin) 
FROM #temp AS t 
WHERE NOT EXISTS (SELECT 1 
        FROM #temp AS It 
        WHERE t.CETA = It.CETA 
          AND t.AIDNEBHNPRAFI = It.AIDNEBHNPRAFI 
          AND t.DFIN = DATEADD(SECOND, -1, it.DDEB) 
        ) 
) 
SELECT Starts.ddeb, Finishes.DFIN, starts.ceta, starts.AIDNEBHNPRAFI 
FROM Starts 
INNER JOIN Finishes 
ON Starts.AIDNEBHNPRAFI = Finishes.AIDNEBHNPRAFI 
AND Starts.CETA = Finishes.CETA 
AND Starts.RowSeq = Finishes.RowSeq 
ORDER BY Starts.ddeb 

Результаты:

DDEB DFIN CETA AIDNEBHNPRAFI 

2006-03-01 00:00:00.000 2008-08-31 23:59:59.000 1 231272 

2008-09-01 00:00:00.000 2008-10-31 23:59:59.000 2 231272 

2008-11-01 00:00:00.000 2010-01-31 23:59:59.000 1 231272 

2010-02-01 00:00:00.000 9999-12-31 23:59:59.000 14 231272 
0

Wes H получил мой на правильном пути. Мой коллега немного посмотрел на код и придумал это. И он обрабатывает 9,6 миллиона строк за 4 минуты и 8 секунд.

With CTETest(StartDate, EndDate, value, ID) 
AS 
(
SELECT [DDEB], 
     Case When 
      DFIN = '9999-12-31 23:59:59.000' 
      THEN 
         DFIN 
      ELSE 
       DATEADD(SECOND, 1, [DFIN]) 
      END 
    , [CETA] 
    , [AIDNEBHNPRAFI] as ID 
FROM [dbo].[TBYDWHTEBHNPRAFIVRS] 
where DFIN>DDEB and BRRDDEL<>1 and CSTUVRS = 1 
), 

T1(ID, value, isStartTS, isEndTS, TS) 
AS (
SELECT ID, value, 1, 0, StartDate 
FROM CTETest 
UNION ALL 
SELECT ID, value, 0, 1, EndDate 
FROM CTETest 
), 

T2 (ID, value, TS, cr_ttl, prv_ttl) as ( 
select ID, value, TS, 
sum(isStartTS) over (Partition by ID, value order by TS,isEndTS rows  unbounded Preceding) - 
sum(isEndTS) over (partition by ID, Value order by TS,isEndTS rows unbounded preceding)as cr_ttl, 
sum(isStartTS) over (Partition by ID, value order by TS,isEndTS rows  between unbounded Preceding and 1 preceding) - 
sum(isEndTS) over (partition by ID, value order by ts,isEndTS rows between  unbounded preceding and 1 preceding)as prv_ttl 
from T1), 

T3 (ID, value, TS, cr_ttl, prv_ttl) as (
Select ID, value, TS, cr_ttl, prv_ttl 
from T2 
where cr_ttl = 0 or prv_ttl is null or prv_ttl = 0 
), 

T4 (ID, value, StartDate ,EndDate, prv_ttl) as ( 
select ID, value, TS, 
max(TS) over (partition by ID, value order by TS rows between current row  and 1 following), 
prv_ttl 
from T3 
) 

select ID as [AIDNEBHNPRAFI], value as CETA,StartDate as DDEB, Case When 
       EndDate = '9999-12-31 23:59:59.000' THEN EndDate ELSE DateADD (second, -1, EndDate) END as DFIN 
      into  [dbo].[TBYDWHTEBHNPRAFIVRS_CTE] 
from T4 
where prv_ttl is Null or prv_ttl = 0 
--order by ID, StartDate