忽略mysql select中的后续等效行

时间:2018-11-19 16:05:48

标签: mysql sql logging data-cleaning redundancy

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

 --------------------------------------
|  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  |
 --------------------------------------

通过编程,可以很容易地删除这些冗余,但是使用纯SQL时,我有点迷失了。精通SQL查询的人将如何处理呢?

谢谢

编辑:基本上,对于实体1,日志中动作的连续性为A->A->B->A->A->A->B,我希望有一个选择返回带有这些动作A->B->A->B的行

2 个答案:

答案 0 :(得分:0)

这是如果按日期顺序添加行。

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

答案 1 :(得分:-1)

您希望每个实体的行都具有最新操作。我会的:

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中执行类似的操作,但是窗口功能(如果可用)更简单。