2017-05-02 29 views
0

나는 활성/비활성이되는 임원의 활동 변경 내역을 가지고 있습니다.시퀀스에서 오류를 찾으십시오.

OfficerID ChangeTo ChangeDate 
1   active  2017-05-01 
1   active  2017-05-02 
1   inactive 2017-05-04 
6   active  2013-09-09 
6   inactive 2016-04-14 
6   recruit 2016-06-22 
6   active  2016-06-23 
6   inactive 2017-04-30 

위의 경우, 임원 ID 1은 5 월 1 일부터 5 월 4 일까지 활성화됩니다.

이것은 본질적으로 '하우스 키핑'작업입니다. 두 번째 행은 필요하지 않으므로 삭제해야합니다. 스케줄에 따라 이벤트를 링크하는 MySQL 프로 시저에서이 작업을 수행하려고합니다. 이 행을 식별 할 수있는 쿼리가 필요하지만 방법이 확실하지 않습니다.

이전 시스템에서는 순서가 지정된 목록을 반복하고 이전 값과 이전 값을 비교했습니다. MySQL에서 루프가 권장되지 않는다는 것을 읽었으므로 쿼리만으로이 작업을 수행하는 방법을 파악하려고합니다. 내가 기대했다

SELECT 
    a.ActivityID, a.OfficerID, a.ChangeTo, a.ChangeDate 
FROM 
    tbl_Officers_Activity as a 
    INNER JOIN tbl_Officers_Activity AS b 
     ON a.OfficerID = b.OfficerID 
     AND a.ChangeDate > b.ChangeDate 
     AND a.ChangeTo = b.ChangeTo 
    INNER JOIN tbl_Officers_Activity AS c 
     ON a.OfficerID = c.OfficerID 
     AND a.ChangeDate < c.ChangeDate 
     AND a.ChangeTo <> c.ChangeTo 
ORDER BY 
    OfficerID, 
    ChangeDate; 

나는 조인에 필요한 기준을 어떻게 든을 포함 할 수 있습니다,하지만 난 손실에있어 : ​​

나는 다음 시도했다. 어떤 도움이라도 대단히 감사하겠습니다. 그래서 처음에는 그것을 유도했다,

MySQL이 row_Number 기능을 가지고 있지 않습니다

답변

0

이 당신이

SQLFIddle Demo

select a1.officerid,a1.changedate,a1.changeto_a as changeto 
From 
(select a.officerid,a.changedate,max(a.changeto) as changeto_a,count(*) as rnk 
from tbl_Officers_Activity a 
inner join tbl_Officers_Activity b 
on a.OfficerID=b.OfficerID 
and a.ChangeDate>=b.ChangeDate 
group by a.officerid,a.changedate) a1 
left join 
(select a.officerid,a.changedate,max(a.changeto) as changeto_b,count(*) +1 as rnk 
from tbl_Officers_Activity a 
inner join tbl_Officers_Activity b 
on a.OfficerID=b.OfficerID 
and a.ChangeDate>=b.ChangeDate 
group by a.officerid,a.changedate) b1 
on a1.officerid=b1.officerid 
and a1.rnk=b1.rnk 
where changeto_a = changeto_b 

설명이 필요한 것입니다. 이 쿼리를 사용하여 row_number을 얻었습니다.이 쿼리의 이름은 rnk입니다. 표 a1으로 전화하십시오. MySQL은 LEAD 기능도하지 않는

(select a.officerid,a.changedate,max(a.changeto) as changeto_a,count(*) as rnk 
from tbl_Officers_Activity a 
inner join tbl_Officers_Activity b 
on a.OfficerID=b.OfficerID 
and a.ChangeDate>=b.ChangeDate 
group by a.officerid,a.changedate) 

지금, 나는 그것을 b1 호출, 다시 위의 쿼리를 사용하고 rnk+1rnk을 변경하여 산출했다.

이제 LEAD를 복제 할

, I left joined a1

b1 지금 당신은 당신의 출력을 얻을 수 있습니다, 같은 changeto을 찾기 위해 where 절을 사용하여.

+0

감사합니다 - 당신이 당신의 입력. 나는 당신과 비슷한 솔루션으로 끝났지 만, 더 많은 데이터로 실행하면 솔루션이 부정확 해졌습니다. 나는 이것이 왜 그런지 이해하는 데 관심이있다. 이 문제에 대해 어떤 생각을 할애 할 수 있습니까? – ShadeBlack

+0

가능한 경우, 내가 준 바이올린을 사용하고 잘못된 동작을 복제하기 위해 일부 행을 추가하십시오. 스크린 샷에서는 그다지 명확하지 않습니다. – Utsav

0

내 솔루션은 Utsav가 게시 한 솔루션과 비슷하지만 솔루션을 내 솔루션과 비교 한 후 정확하고 정확하지 않은 것으로 나타났습니다. solution results comparison

제 솔루션의 경우 자동 증분 기본 키가있는 초기 정렬 목록의 임시 테이블을 만듭니다. 그런 다음 임시 테이블을 복제하고 기본 Pk가 자체 +1과 같고 상태 변경과 동일하게 자체에 가입하십시오.

내 절차는 다음과 같이 끝 :

-- create temp table 
DROP TABLE IF EXISTS tmp_act; 
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_act (
    AutoID INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    ActivityID INT(11), 
    OfficerID INT(11), 
    ChangeTo text 
); 

-- temp data 
insert into tmp_act (ActivityID,OfficerID,ChangeTo) 
    SELECT 
     a.ActivityID, a.OfficerID, a.ChangeTo 
    FROM 
     tbl_Officers_Activity as a 
    ORDER BY 
     OfficerID, 
     ChangeDate; 

-- housekeeping 
DROP TABLE IF EXISTS tmp_act1; 
DROP TABLE IF EXISTS tmp_act2; 
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_act1 AS (SELECT * FROM tmp_act); 
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_act2 AS (SELECT * FROM tmp_act); 
SELECT 
    a.AutoID, a.ActivityID, a.OfficerID, a.ChangeTo 
FROM 
    tmp_act1 as a 
    INNER JOIN tmp_act2 AS b 
     ON a.OfficerID = b.OfficerID 
     AND a.ChangeTo = b.ChangeTo 
     AND a.AutoID = b.AutoID+1;