복붙노트

[SQL] SQL은 : 행을 선택하는 열 값은 이전 행 변경된 곳

SQL

SQL은 : 행을 선택하는 열 값은 이전 행 변경된 곳

의 난이 (MySQL의) 데이터베이스가 있다고 가정 해 봅시다 증가 타임 스탬프으로 분류 :

Timestamp   System StatusA StatusB 
2011-01-01     A      Ok     Ok      
2011-01-02     B      Ok     Ok     
2011-01-03     A     Fail   Fail     
2011-01-04     B      Ok    Fail     
2011-01-05     A     Fail    Ok      
2011-01-06     A      Ok     Ok      
2011-01-07     B     Fail   Fail    

StatusA가 해당 시스템의 이전 행에서 변경할 경우 어떻게 행을 선택합니까? StatusB은 (난 단지 StatusA이 변경되지 않는 각 시스템에 대한 많은 연속 행이있을 수 있음을 설명하기 위해이 질문에 보여) 문제가되지 않습니다. 위의 예에서, 쿼리는 행 2011-01-03, 2011-01-06, 2011-01-07 (StatusA은과 SystemA 위해 2011-01-01 및 2011-01-03 사이에서 변화)를 호출한다.

쿼리는 테이블 만개의 레코드를 갖는 신속하게 실행해야한다.

감사

해결법

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

    1.

    SELECT a.*
    FROM tableX AS a
    WHERE a.StatusA <>
          ( SELECT b.StatusA
            FROM tableX AS b
            WHERE a.System = b.System
              AND a.Timestamp > b.Timestamp
            ORDER BY b.Timestamp DESC
            LIMIT 1
          ) 
    

    하지만 당신은 (시스템, 타임 스탬프)에 인덱스뿐만 아니라이 (시도 할 수 있습니다 :

    SELECT System, Timestamp, StatusA, StatusB
    FROM
      ( SELECT (@statusPre <> statusA AND @systemPre=System) AS statusChanged
             , System, Timestamp, StatusA, StatusB
             , @statusPre := StatusA
             , @systemPre := System
        FROM tableX
           , (SELECT @statusPre:=NULL, @systemPre:=NULL) AS d
        ORDER BY System
               , Timestamp
      ) AS good
    WHERE statusChanged ;
    
  2. ==============================

    2.

    select a.Timestamp, a.System, a.StatusA, a.StatusB
    from tableX as a
    cross join tableX as b
    where a.System = b.System
    and a.Timestamp > b.Timestamp
    and not exists (select * 
        from tableX as c
        where a.System = c.System
        and a.Timestamp > c.Timestamp
        and c.Timestamp > b.Timestamp
    )
    and a.StatusA <> b.StatusA;
    

    코멘트를 해결하는 업데이트 : 왜 내부 크로스 조인을 대신 조인을 사용하지?

    문제는 MySQL의 솔루션을 요청합니다. 문서에 따르면 :

    이 수단이 중 하나가 작동 할 조인.

    조건 a.System = b.System은 아마 INNER이 경우에 더 좋은 것 조인을 사용하도록 '에 가입하는 방법 테이블'카테고리에 해당.

    모두 동일한 결과를 생성하기 때문에, 차이는 성능에있을 수 있습니다. 그들이 가입을 할 인덱스 나 해시를 사용하는지 여부 - 빠른 I는 내부적으로 구현 조인있는 방법을 알 필요가있을 것이다라고합니다.

  3. ==============================

    3.사용 ROWNUM

    사용 ROWNUM

    나는 20000 행에 0.05 초있어

    select a1.*
      from (select rownum R_NUM, TIMESTAMP, System, StatusA from TableX) a1 
      join (select rownum R_NUM, TIMESTAMP, SYSTEM, STATUSA from TABLEX) a2 
        on a1.R_NUM = a2.R_NUM+1 
     where a1.system = a2.system 
       and a1.StatusA != a2.StatusA
    
  4. ==============================

    4.여기에 비슷한 논리를 갖는 약간 짧은 버전입니다. 나는 그것을 효율적 확신 너무 자주 테스트했습니다; 그것은 상관 하위 쿼리 (WHERE NOT EXISIS)를 제거 주로 때문이다.

    여기에 비슷한 논리를 갖는 약간 짧은 버전입니다. 나는 그것을 효율적 확신 너무 자주 테스트했습니다; 그것은 상관 하위 쿼리 (WHERE NOT EXISIS)를 제거 주로 때문이다.

    "C"가 있는지 b는 바로 아래에 있음이 확인에 - 그것은합니다 (NULL 테스트를 통해) (사이) C 찾을 수 없습니다 말했다.

    SELECT a.Timestamp, a.System, a.StatusA, a.StatusB
    FROM tableX AS a
    JOIN tableX AS b
        ON a.System = b.System
        AND a.Timestamp > b.Timestamp
    LEFT JOIN tableX AS c
        ON a.System = b.System
        AND a.Timestamp > c.Timestamp
        AND b.Timestamp < c.Timestamp
    WHERE c.System IS NULL
        AND a.StatusA <> b.StatusA;
    
  5. ==============================

    5.에고의 대답은 하나의 작은 변화에 MSSQL에서 날 위해 일했습니다. 와 ROWNUM 문을 대체했다 :

    에고의 대답은 하나의 작은 변화에 MSSQL에서 날 위해 일했습니다. 와 ROWNUM 문을 대체했다 :

    select row_number () over (order by TIMESTAMP) as R_NUM, ...
    
  6. ==============================

    6.

    SELECT   a.*
    FROM    (select row_number() over (partition by System order by Timestamp asc) as aRow, Timestamp, System, StatusA, StatusB from tableX) as a
    left join (select row_number() over (partition by System order by Timestamp asc) as bRow, Timestamp, System, StatusA, StatusB from tableX) as b on a.aRow = b.bRow + 1 and a.System = b.System 
    where (a.StatusA != b.StatusA or b.StatusA is null)
    

    값이 다른 곳은 첫 번째 행과 행을 반환합니다.

  7. from https://stackoverflow.com/questions/6560000/sql-selecting-rows-where-column-value-changed-from-previous-row by cc-by-sa and MIT license