Mysql 查找序列中的错误

Mysql 查找序列中的错误,mysql,sql,procedure,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-

我有一份变为现役/非现役军官的活动变更记录

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;
选择
a、 ActivityID,a.OfficeId,a.ChangeTo,a.ChangeDate
从…起
tbl_官员作为
以b的身份参加内部tbl_活动
在a.OfficeId=b.OfficeId上
和a.ChangeDate>b.ChangeDate
a.ChangeTo=b.ChangeTo
以c的身份参加内部tbl_活动
在a.OfficeId=c.OfficeId上
a.ChangeDate
我希望我能以某种方式将我需要的标准嵌入到连接中,但我不知所措。任何帮助都将不胜感激。

这是您所需要的

说明:

MySQL没有
row\u 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
,我将
b1


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

我的解决方案最终与Utsav发布的类似,但是,在比较他的解决方案和我的解决方案后,我发现我的解决方案是准确的,而他的解决方案是不准确的

对于我的解决方案,我使用自动增量主键为初始有序列表创建一个临时表。然后克隆临时表并在其自身上联接,主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;

谢谢你的意见。我最终得到了一个类似于您的解决方案,但当运行更多数据时,您的解决方案返回不准确。我很想知道为什么会这样。你能在这件事上省点心思吗?如果可能的话,用我给你的小提琴,加上一些行来复制不正确的行为。从截图上看不太明显。
-- 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;