忽略mysql select中的后续等效行

r55awzrz  于 2021-06-19  发布在  Mysql
关注(0)|答案(2)|浏览(282)

我需要删除历史日志数据中的冗余。因此给出下表:

--------------------------------------
|  entity_id  |  action  |   date      |
 --------------------------------------
|      1      |    'A'   | 2018-01-01  |
|x     1      |    'A'   | 2018-01-01  |
|      1      |    'B'   | 2018-01-01  |
|      1      |    'A'   | 2018-01-02  |
|      8      |    'A'   | 2018-01-02  |
|x     1      |    'A'   | 2018-01-03  |
|x     8      |    'A'   | 2018-01-04  |
|x     1      |    'A'   | 2018-01-05  |
|      1      |    'B'   | 2018-01-05  |
 --------------------------------------

我想去掉带(x)的。简而言之,我想忽略任何具有实体随后执行的相同操作的行。因此,我想要一个返回以下结果的查询

--------------------------------------
|  entity_id  |  action  |   date      |
 --------------------------------------
|      1      |    'A'   | 2018-01-01  |
|      1      |    'B'   | 2018-01-01  |
|      1      |    'A'   | 2018-01-02  |
|      8      |    'A'   | 2018-01-02  |
|      1      |    'B'   | 2018-01-05  |
 --------------------------------------

从编程的Angular 来说,删除这些冗余很容易,但是使用纯sql,我有点迷路了。熟悉sql查询的人如何处理这个问题?
谢谢
编辑:基本上,对于实体1,日志中操作的顺序是 A->A->B->A->A->A->B ,我想要一个select返回包含这些操作的行 A->B->A->B

ecfsfe2w

ecfsfe2w1#

如果按日期顺序添加行,则会出现这种情况。

select entity_id, action, min(date)
from table
group by entity id, action
oxalkeyp

oxalkeyp2#

您需要包含每个实体的最新操作的行。我会做:

select t.*
from t
where t.date = (select min(t2.date)
                from t t2
                where t2.entity_id = t.entity_id and t2.action = t.action
               );

编辑:
在mysql 8+中,您只需使用 lag() :

select t.*
from (select t.*,
             lag(action) over (partition by entity_id order by date) as prev_action
      from t
     ) t
where prev_action is null or prev_action > action;

您可以在mysql的早期版本中执行类似的操作,但是窗口函数如果可用的话会更简单。

相关问题