查找序列中的错误

时间:2017-05-02 15:57:03

标签: mysql sql procedure

我有一个活动更改日志的官员变得活跃/不活跃。

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;

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

2 个答案:

答案 0 :(得分: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功能,我再次使用上述查询并将rnk更改为rnk+1,并将其称为b1

现在要复制LEAD,我left joined a1b1

现在使用where子句查找相同的changeto,您可以获得输出。

答案 1 :(得分: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;