MySQL - 选择第一个/最后一个不同的行

时间:2016-12-12 21:23:59

标签: mysql sql select

所以我得到了一张有这种基本结构的表格(我试图消除不相关的字段):

EmpID  EventDate   Timestamp            State   State_Time
1111   2016-12-01  2016-12-01 00:00:00  a       01:00:00
1111   2016-12-01  2016-12-01 01:00:00  a       01:00:00
1111   2016-12-01  2016-12-01 02:00:00  a       01:00:00
1111   2016-12-01  2016-12-01 03:00:00  a       01:00:00
1111   2016-12-01  2016-12-01 04:00:00  a       00:24:00
1111   2016-12-01  2016-12-01 04:24:00  b       00:03:00      1*
1111   2016-12-01  2016-12-01 04:27:00  c       00:33:00      2*
1111   2016-12-01  2016-12-01 05:00:00  c       01:00:00
1111   2016-12-01  2016-12-01 06:00:00  c       01:00:00
2222   2016-12-01  2016-12-01 10:21:00  c       00:03:00
2222   2016-12-01  2016-12-01 10:24:00  a       00:10:00
2222   2016-12-01  2016-12-01 10:34:00  b       00:15:00
3333   2016-12-01  2016-12-01 00:00:00  c       01:00:00
3333   2016-12-01  2016-12-01 01:00:00  c       01:00:00
3333   2016-12-01  2016-12-01 02:00:00  c       01:00:00
3333   2016-12-01  2016-12-01 03:00:00  c       01:00:00
3333   2016-12-01  2016-12-01 04:00:00  c       01:00:00
3333   2016-12-01  2016-12-01 05:00:00  c       01:00:00
3333   2016-12-01  2016-12-01 06:00:00  c       00:21:00
3333   2016-12-01  2016-12-01 06:21:00  a       00:03:00      1*
3333   2016-12-01  2016-12-01 06:24:00  b       00:36:00      2*
3333   2016-12-01  2016-12-01 07:00:00  b       01:00:00
3333   2016-12-01  2016-12-01 08:00:00  b       01:00:00

我需要能够拉出两种特定类型的行(单独的查询很好/更好)。

  1. 状态发生变化,但EmpID和EventDate保持不变(与前一行相同)。
  2. 系列的第一个记录,其中State不会为剩余的EventDate更改(具有常量EmpID和State)。
  3. 我已添加*以表明我正在寻找哪个。虽然此数据集仅包含一个日期,但实际来源包含的数据目前跨越一年,并且还在继续增长。

    感谢您提供任何帮助!

1 个答案:

答案 0 :(得分:0)

您的规则(1)选择的行数多于您用1 *标记的行数。例如,4:27中的那个。

这是查询(1):

SELECT a.*
 FROM tab as a
 JOIN tab as b
 WHERE a.EmpID = b.EmpID
   AND a.EventDate = b.EventDate
   AND a.State <> b.State
   AND b.TimeStamp = (SELECT max(Timestamp) 
                  FROM tab WHERE TimeStamp < a.TimeStamp);

这是查询(2)。它运行了一段时间。

SELECT a.*
  FROM tab as a
  WHERE (NOT EXISTS
     (SELECT * FROM tab as b 
        WHERE a.EmpID = b.EmpID
              AND a.EventDate = b.EventDate
              AND a.State = b.State
              AND b.Timestamp < a.Timestamp))
    AND (NOT EXISTS
     (SELECT * FROM tab as b
        WHERE a.EmpID = b.EmpID
          AND a.EventDate = b.EventDate
          AND a.State<> b.State
          AND b.Timestamp > a.Timestamp))
    AND (EXISTS
     (SELECT * FROM tab as b 
        WHERE a.EmpID = b.EmpID
          AND a.EventDate = b.EventDate
          AND a.State = b.State
          AND b.Timestamp > a.Timestamp))

查询2中的三个WHERE是: 1.确保没有相同的emp,date和state的先前记录。 2.确保没有相同的emp和日期的未来记录,具有不同的状态。 3.确保相同的emp,date和state至少有一个未来记录(按顺序说,链实际上已经开始)。