2017-05-02 37 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 

在上述情况下,主管身份证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; 

我希望我能以某种方式嵌入我需要到连接的标准,但我不知所措。任何帮助将不胜感激。

回答

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 

说明:

MySQL没有row_Number功能,所以首先我必须得到它。我用这个查询得到row_number,在查询中它的名字是rnk。致电表a1

(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) 

现在,作为MySQL没有LEAD功能还可以,我再次使用上面的查询,并改变rnkrnk+1,称这是b1派生它。

我们复制LEAD,我left joineda1b1

现在使用WHERE子句找到相同changeto,你可以得到你的输出。

+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;