복붙노트

[SQL] SQL : 연속 기록에 그룹으로

SQL

SQL : 연속 기록에 그룹으로

약간 까다로운 SQL 질문 (우리는 SQL 서버 2000을 실행하는).

나는 STORECOUNT을 다음과 같은 테이블이 -

WeekEndDate    StoreCount
2010-07-25     359
2010-07-18     359
2010-07-11     358
2010-07-04     358
2010-06-27     358
2010-06-20     358
2010-06-13     358
2010-06-06     359
2010-05-30     360
2010-05-23     360
2010-05-16     360

나는 다음과 같은 출력으로이 켜려고합니다 -

StartDate    EndDate       StoreCount
2010-07-18   2010-07-25    359
2010-06-13   2010-07-11    358
2010-06-06   2010-06-06    359
2010-05-16   2010-05-30    360

당신이 볼 수 있듯이 그들이 함께 순서대로 실행으로, 나는 단지로, 그룹에 매장 수를 꿔.

해결법

  1. ==============================

    1.여기에 캔에서 킥입니다 만 그것은 SS2k에서 사용할 수없는 구문 수 있습니다. 내가 주변에 더 이상 SS의 해당 버전이없는 것처럼 실제로 오라클에 작성되었습니다. 유일한 캐치는이 (가) 선택의 선택이 될 수 ... (내가 SS2k을 사용 했으므로하면서 기능을 사용할 수 다시 다음하지 않았다 기억하기 어렵다 그래서는이있었습니다.)

    여기에 캔에서 킥입니다 만 그것은 SS2k에서 사용할 수없는 구문 수 있습니다. 내가 주변에 더 이상 SS의 해당 버전이없는 것처럼 실제로 오라클에 작성되었습니다. 유일한 캐치는이 (가) 선택의 선택이 될 수 ... (내가 SS2k을 사용 했으므로하면서 기능을 사용할 수 다시 다음하지 않았다 기억하기 어렵다 그래서는이있었습니다.)

    select min(weekenddate) as start_date, end_date, storecount
    from (
    select s1.weekenddate
         , (select max(weekenddate)
              from store_stats s2
             where s2.storecount = s1.storecount
               and not exists (select null
                                 from store_stats s3
                                where s3.weekenddate < s2.weekenddate
                                  and s3.weekenddate > s1.weekenddate
                                  and s3.storecount <> s1.storecount)
           ) as end_date
         , s1.storecount
    from store_stats s1
    ) result
    group by end_date, storecount
    order by 1 desc
    
    
    START_DATE END_DATE   STORECOUNT
    ---------- ---------- ----------
    2010-07-18 2010-07-25        359
    2010-06-13 2010-07-11        358
    2010-06-06 2010-06-06        359
    2010-05-16 2010-05-30        360
    
  2. ==============================

    2.사용 커서. 나는 쿼리를 사용하여 sql2k에서 그것을 할 방법을 모르겠어요.

    사용 커서. 나는 쿼리를 사용하여 sql2k에서 그것을 할 방법을 모르겠어요.

    DECLARE @w datetime
    DECLARE @s int
    DECLARE @prev_s int
    DECLARE @start_w datetime
    DECLARE @end_w datetime
    
    CREATE TABLE #zz(start datetime, [end] datetime, StoreCount int)
    
    DECLARE a_cursor CURSOR
    FOR SELECT WeekEndDate, StoreCount FROM Line ORDER BY WeekEndDate DESC, StoreCount
    OPEN a_cursor
    FETCH NEXT FROM a_cursor INTO @w, @s
    WHILE @@FETCH_STATUS = 0
    BEGIN
    
        IF @end_w IS NULL 
        BEGIN
    
            SET @end_w = @w
            SET @start_w = @w     
            SET @prev_s = @s
        END 
        ELSE IF @prev_s <> @s
        BEGIN
           INSERT INTO #zz values(@start_w,  @end_w, @prev_s)
    
           SET @end_w = @w  
           SET @start_w = @w  
           SET @prev_s = @s 
        END ELSE
            SET @start_w = @w 
    
        FETCH NEXT FROM a_cursor INTO @w, @s
    END
    -- add last one
    INSERT INTO #zz values(@start_w, @end_w, @prev_s)
    
    CLOSE a_cursor
    DEALLOCATE a_cursor
    
    SELECT * FROM #zz ORDER BY 1 DESC
    DROP TABLE #zz
    
  3. ==============================

    3.좋아, 여기에 나의 이동합니다.

    좋아, 여기에 나의 이동합니다.

    DECLARE @curDate DATETIME = (SELECT MIN(WeekEndDate) FROM Table_1);
        DECLARE @curCount INT = (SELECT StoreCount FROM Table_1 WHERE WeekEndDate = @curDate);
        DECLARE @sDate DATETIME = GETDATE()
        DECLARE @eDate DATETIME = 0
    
    
        WHILE @eDate < (SELECT MAX(WeekEndDate) FROM Table_1)
        BEGIN
            SELECT @sDate = (SELECT WeekEndDate AS StartDate FROM Table_1 WHERE WeekEndDate = @curDate) -- SELECT START DATE
    
            -- NOW GET THE END DATE IN THIS GROUP
            DECLARE @d1 DATETIME = @curDate
            DECLARE @d2 DATETIME = @curDate
            DECLARE @loop INT = 1
            WHILE @loop = 1
                BEGIN
                    IF ((SELECT StoreCount FROM Table_1 WHERE WeekEndDate = @d1) <> @curCount OR @d1 = (SELECT MAX(WeekEndDate) FROM Table_1)) BEGIN
                        SELECT @eDate = (SELECT TOP(1) WeekEndDate FROM Table_1 WHERE StoreCount = @curCount AND WeekEndDate = @d2 ORDER BY WeekEndDate DESC)
                        SELECT @loop = 0 END
                    ELSE BEGIN
                        SELECT @d2 = @d1 
                        SELECT @d1 = (SELECT TOP(1) WeekEndDate FROM Table_1 WHERE WeekEndDate > @d1 ORDER BY WeekEndDate) END
                END
    
    
            SELECT @sDate AS StartDate, @eDate AS EndDate, @curCount AS StoreCount   -- DO QHATEVER YOU NEED TO DO WITH THE RECORDS HERE
    
            SELECT TOP(1) @curDate = WeekEndDate, @curCount = StoreCount
            FROM Table_1
            WHERE WeekEndDate > @eDate
            GROUP BY WeekEndDate, StoreCount
            ORDER BY WeekEndDate ASC
    
        END
    
  4. ==============================

    4.나는 이것을 설명하는 방법을 잘 모르겠지만, 주어진 작은 데이터 세트에 대해 원하는 결과를 줄 것으로 보인다. 본질적으로,이 값이 변경 시리즈의 포인트를 감지합니다.

    나는 이것을 설명하는 방법을 잘 모르겠지만, 주어진 작은 데이터 세트에 대해 원하는 결과를 줄 것으로 보인다. 본질적으로,이 값이 변경 시리즈의 포인트를 감지합니다.

    내가 쿼리 계획을보고하지 않은, 고통스러운 수 있습니다.

    구문은 SQL 서버 2K와 호환되어야하며,이 Sybase 서버에 시도.

    SELECT  x.StartDate
            , MIN( y.EndDate ) AS EndDate
            , x.StoreCount
    FROM
    ( SELECT
            wed1.WeekEndDate AS StartDate
            , wed1.StoreCount
    FROM
            wed wed1
    LEFT JOIN
            wed wed2
    ON      wed1.WeekEndDate = DATEADD( DAY, 7, wed2.WeekEndDate )
    WHERE
            wed1.StoreCount != ISNULL( wed2.StoreCount, wed1.StoreCount - 1 )
    ) x,
    ( SELECT
            wed1.WeekEndDate AS EndDate
    FROM
            wed wed1
    LEFT JOIN
            wed wed2
    ON      wed1.WeekEndDate = DATEADD( DAY, -7, wed2.WeekEndDate )
    WHERE
            wed1.StoreCount != ISNULL( wed2.StoreCount, wed1.StoreCount - 1 )
    ) y
    WHERE
            y.EndDate >= x.StartDate
    GROUP BY
            x.StartDate
    HAVING
            x.StartDate = MIN( x.StartDate )
    ORDER BY
            1 DESC
    
    StartDate    EndDate      StoreCount
    ------------ ------------ -----------
     Jul 18 2010  Jul 25 2010         359
     Jun 13 2010  Jul 11 2010         358
     Jun  6 2010  Jun  6 2010         359
     May 16 2010  May 30 2010         360
    
  5. ==============================

    5.이 간단한 해결책을 시도해보십시오 :

    이 간단한 해결책을 시도해보십시오 :

    create table x  (weekEndDate char(10), storeCount int);
    insert into x values
    ('2010-07-25',359),
    ('2010-07-18',359),
    ('2010-07-11',358),
    ('2010-07-04',358),
    ('2010-06-27',358),
    ('2010-06-20',358),
    ('2010-06-13',358),
    ('2010-06-06',359),
    ('2010-05-30',360),
    ('2010-05-23',360),
    ('2010-05-16',360);
    select min(weekenddate) as startdate, max(weekenddate) as enddate, min(storecount) as storecount 
    from 
    (select weekenddate, storecount, concat(row_number() over (order by weekenddate) -row_number() over (partition by storecount order by weekenddate),'|',storecount) as groupkey from x) w
    group by groupkey order by startdate desc;
    

    sqlfiddle

  6. from https://stackoverflow.com/questions/3410687/sql-group-by-on-consecutive-records by cc-by-sa and MIT license