当前位置: 首页 > 知识库问答 >
问题:

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

朱保赫
2023-03-14

假设我有这个(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    

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

查询应该在表中有数万条记录的情况下快速执行。

谢谢

共有3个答案

柴良哲
2023-03-14

使用行号

我有0.05秒处理20000行

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
辛成周
2023-03-14
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;

更新处理注释:为什么不使用内部联接而不是交叉联接?

这个问题需要一个MySQL解决方案。 根据文件:

在MySQL中,CROSS JOIN是与内部JOIN等效的语法(它们可以相互替换)。 在标准SQL中,它们是不等价的。 内部联接与ON子句一起使用,否则使用交叉联接。

这意味着这两种连接中的任何一种都可以工作。

与ON一起使用的conditional_expr是可以在WHERE子句中使用的任何形式的条件表达式。 通常,对于指定如何联接表的条件,您应该使用ON子句,而对于在结果集中需要哪些行,您应该使用WHERE子句。

条件a.system=b.system可能属于'How to join tables'类别,因此在这种情况下使用内部联接会更好。

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

郎和志
2023-03-14
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
      ) 

但是您也可以尝试(使用(系统,时间戳)上的索引:

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 ;
 类似资料:
  • 问题内容: 假设我有这个(MySQL)数据库,按增加的时间戳排序: 如何从该系统的上一行中选择StatusA更改的行?StatusB无关紧要(我在此问题中展示它只是为了说明每个系统可能有许多连续的行,其中StatusA不变)。在上面的示例中,查询应返回2011-01-03行(对于SystemA,StatusA在2011-01-01和2011-01-03之间更改),2011-01-06、2011-0

  • 问题内容: 我需要帮助或想法如何编写它,一个mysql语句。当特定列的值更改时,我需要选择一行。此后具有相同值的行不应选择。例如,我们有一个像这样的表,用以下值填充: 如果我想在status_1更改时选择行,则查询应选择ID为1和5的行,如果我正在使用status_2的ID为:1、3、5、7的行,并且如果我使用status_3的所有ID,则为ID 。希望有人可以在过去的所有时间里为我提供帮助。 提

  • 我有这个,它绑定了一个变更事件。在其内部值的中,我想在另一个选择列表中选择一个特定的元素,即其中的一个特定选项。 然而它并不起作用。在主服务中有一些服务,如果选择了子服务,就不需要子服务,因此应该选择默认的。 null null

  • 问题内容: 想要改善这篇文章吗? 提供此问题的详细答案,包括引文和为什么答案正确的解释。答案不够详细的答案可能会被编辑或删除。 这个问题已经在这里有了答案 : 检索每个组中的最后一个记录-MySQL (27个答案) 去年关闭。 我有此表用于文档(此处为简化版): 如何为每个ID选择一行,而仅选择最大转速? 根据上述数据,结果应包含两行:和。我正在使用 MySQL 。 目前,我在循环中使用检查来检测

  • 问题内容: 我有表,其中有一列可能在突发中具有相同的值。像这样: 现在,我要修剪重复值的行,并仅选择第一个出现的行。 对于上表,结果应为: 如何在SQL中执行此操作? 请注意,仅应删除突发行,并且可以在非突发行中重复值! &在样本结果中重复。 编辑: 我用这个实现了它: 但这仅在ID为顺序的时才有效。id(已删除的ID)之间有间隔,查询中断。我怎样才能解决这个问题? 问题答案: 您可以使用半联接来

  • 问题内容: 基本上,我有下表: 我需要在每个列中获得唯一的条目,如以下示例所示: 到目前为止,以下代码片段几乎提供了我想要的内容,但可能会返回一些值,这在当前列中不是唯一的: 也无济于事,因为它返回唯一的行,而不是其值 编辑: 选择顺序无关紧要 问题答案: 即使使用Dimitri提到的有问题的组合,这也对我有用。我不知道这对于大音量有多快 SQLFiddle当前不适用于我,这是我的测试脚本: 输出

  • 问题内容: 我有一个MySQL表,其中包含以下类型的信息: 这是我用来从该表获取数据的脚本示例: 该脚本显示表格中的每个日期,例如 我只想显示唯一的日期,例如 问题答案: 在MySQL中使用DISTINCT运算符:

  • 问题内容: 在MSSQL服务器上,给出以下表: 我可以发出类似的查询: 并得到类似: 如果我想要这样的数据,查询数据库的最有效方法是什么? 数据库结构要复杂得多,不幸的是我无法更改它。 编辑 :解决方案不应在查询中使用和作为硬编码值。 问题答案: 对于SQL Server 2005+,可以使用动态SQL和。