SQL:选择列值从上一行更改的行

Jim*_*mmy 33 mysql 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    
Run Code Online (Sandbox Code Playgroud)

如何选择StatusA从该系统的上一行更改的行?StatusB无关紧要(我在这个问题中只是为了说明StatusA不会改变的每个系统可能有很多连续的行).在上面的示例中,查询应返回2011-01-03行(StatusA在2011-01-01和2011-01-03之间为SystemA更改),2011-01-06,2011-01-07.

查询应该快速执行,表中有数万条记录.

谢谢

ype*_*eᵀᴹ 37

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
      ) 
Run Code Online (Sandbox Code Playgroud)

但你也可以尝试这个(索引(System,Timestamp):

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 ;
Run Code Online (Sandbox Code Playgroud)

  • System上有索引,StatusA,TimeStamp...当你问“索引是什么样子”时,你想知道什么?它们是紫色的,带有粉红色的圆点:) (2认同)
  • 甜!第二个查询在0.0172秒内执行! (2认同)

Jir*_*iri 10

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;
Run Code Online (Sandbox Code Playgroud)

更新寻址评论: 为什么不使用内部联接而不是交叉联接?

这个问题要求MySQL解决方案.根据文件:

在MySQL中,CROSS JOIN是一个与INNER JOIN相当的语法(它们可以相互替换).在标准SQL中,它们不等效.INNER JOIN与ON子句一起使用,否则使用CROSS JOIN.

这意味着这些连接中的任何一个都可以工作.

与ON一起使用的conditional_expr是可以在WHERE子句中使用的表单的任何条件表达式.通常,您应该将ON子句用于指定如何连接表的条件,并使用WHERE子句来限制结果集中所需的行.

条件a.System = b.System可能属于"如何连接表"类别,因此在这种情况下使用INNER JOIN会更好.

由于两者产生相同的结果,因此差异可能在于性能.要说哪个更快,我需要知道如何在内部实现连接 - 无论是使用索引还是哈希来进行连接.

  • `交叉连接B,其中Ax = Bx`?为什么不在'Ax = Bx`上的内连接B?否则,确实很好!(1) (2认同)

小智 7

使用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
Run Code Online (Sandbox Code Playgroud)