2017-02-17 4 views
-1

ゆっくりと変化する次元のような開始および終了データを持つさまざまなレコードを含むテーブルを通過するSQLコードです。ディメンションを確認しているうちに、開始日が終了日を過ぎていないことが判明しました。そこで、テーブルをループして、開始日と終了日を再作成して、開始日と終了日が実際に使用可能な日付の最小値/最大値であることを確認します。しかし、このプロセスは、900万行を処理するには時間がかかります。私は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 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 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.0002 231272
2008-11-01 00:00:00.000 2010-01-31 23:59:59.000 1 231272
2010-02-01 00:00:00 9999-12-31 23:59:59 14 231272

+2

質問を単純化して最小化するか、誰かを雇うかのどちらかです。 – jarlh

+0

@jarlh、あなたのコメントは、*あなたが言う、または誰かを雇う* ... :) – Rahul

+0

@Rahul、しかし私はこの誰かではありません。 – jarlh

答えて

0

これは試みです。返された結果は一致しましたが、より多くのデータでテストする必要があります。私もデータ型について仮定しました。あなたが違う場合は、それに応じて更新する必要があります。 CTEは、開始時刻と終了時刻の連続するパートナーを持たない(停止と次の開始の間で1秒が異なる)間隔を識別します。その後、これらの時間にシーケンス番号を割り当て、シーケンスに基づいて開始時刻を&停止時間に加算します。

具体的には、2006年3月1日の開始時間には直前の停止時間が含まれていないので、それが含まれ、そのグループの最初の開始シーケンスです。 2008年11月1日は、同じ基準を満たし、そのグループの次の開始シーケンスです。 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

ウェス・Hは、右のトラックに私を得ました。私の同僚はコードをもう少し見て、これを思いついた。そして、4分8秒で9,600万行を処理します。

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 
関連する問題