MySQL - 检查连续列是不是相同并仅显示那些行

Posted

技术标签:

【中文标题】MySQL - 检查连续列是不是相同并仅显示那些行【英文标题】:MySQL - Check if consecutive columns are the same and display only those rowsMySQL - 检查连续列是否相同并仅显示那些行 【发布时间】:2014-03-07 15:52:11 【问题描述】:

我有一个 events 表,其中包含与这些 ID 对应的 ID (id) 和日期 (eventDate)(ideventDate 不是表中唯一的列)。

SQLFiddle here。

+--------+----+---------------------+
| row_id | id | eventDate           |
+--------+----+---------------------+
|      1 |  1 | 2014-02-27 23:19:41 |
|      2 |  1 | 2014-02-27 23:21:41 |
|      3 |  1 | 2014-02-27 23:21:41 |
|      4 |  2 | 2014-02-27 23:23:08 |
|      5 |  2 | 2014-02-27 23:25:08 |
|      6 |  2 | 2014-02-27 23:25:08 |
|      9 |  3 | 2014-02-28 15:36:55 |
|      8 |  3 | 2014-02-28 15:36:55 |
|      7 |  3 | 2014-02-28 15:34:55 |
|     10 |  4 | 2014-02-28 19:31:31 |
|     11 |  4 | 2014-02-28 19:33:31 |
|     12 |  4 | 2014-02-28 19:33:31 |
|     13 |  5 | 2014-02-28 19:33:34 |
|     14 |  5 | 2014-02-28 19:33:33 |
|     15 |  5 | 2014-02-28 19:31:33 |
|     16 |  6 | 2014-03-04 22:40:21 |
|     17 |  6 | 2014-03-04 22:38:21 |
|     18 |  6 | 2014-03-04 22:40:21 |
|     19 |  7 | 2014-03-04 23:08:37 |
|     20 |  7 | 2014-03-04 23:08:38 |
+--------+----+---------------------+

我只想从表中选择那些连续事件日期对于相同 ID 相同的行。

因此,我只想看到这些条目 -

+----+---------------------+
| id | eventDate           |
+----+---------------------+
|  1 | 2014-02-27 23:21:41 |
|  1 | 2014-02-27 23:21:41 |
|  2 | 2014-02-27 23:25:08 |
|  2 | 2014-02-27 23:25:08 |
|  3 | 2014-02-28 15:36:55 |
|  3 | 2014-02-28 15:36:55 |
|  4 | 2014-02-28 19:33:31 |
|  4 | 2014-02-28 19:33:31 |

注意没有

|  6 | 2014-03-04 22:40:21 |
|  6 | 2014-03-04 22:40:21 |

在上面的结果中,因为它们不是连续的。

我知道我可以将 SQL 查询的输出存储在一个文件中,然后使用 unix 工具来执行此操作,但我想知道这是否可以直接通过 SQL 实现。

【问题讨论】:

数据在表中的位置位置是否重要?或者只是给定日期有多个条目?例如,假设您的示例的第 3 行出现在表格的最后。您是否仍想要您提供的完全相同的输出,或者您是否想忽略 id1 的行? @EMS,好点子。就我而言,我意识到这并不重要,但为了这个线程,假设它确实重要。 您可以编辑问题以反映对您而言重要的是eventDate 分组,而不是实际的位置连续重复。许多人可能知道非常有效和聪明的方法来进行分组,而位置重要性是一个不太适合数据库系统的问题(通常,并非总是如此)。 @EMS,实际上,我更改了问题以反映职位确实很重要。 什么决定了记录在输出中的排序方式。您似乎应该能够轻松地更改它们是否“连续”使用您未共享的其他键列或其他属性。 【参考方案1】:

虽然我的 mysql 有点生锈了,但应该能够利用一个组来完成这个。

SELECT t.*
FROM (
    SELECT  
           id,
           eventDate,
           COUNT(0) AS numRows
    FROM tabl
    GROUP BY id, DATE(eventDate)
    HAVING COUNT(0) > 1
    ORDER BY eventDate
) t

然后,如果您需要额外的列,您只需将此关联的子查询连接回原始表。

【讨论】:

一个在sql server世界的习惯=P【参考方案2】:

select id,eventDate from your_tableName where eventDate in (select eventDate from your_tableName group by id,eventDate have count(eventDate) > 1);

【讨论】:

不处理连续问题 @vogomatix 不,它没有,如果有多个匹配项,它会简单地组合所有类似 id 和 eventDate 列。它仍然会包含 id 6。【参考方案3】:
select ta.id, ta.eventDate from
(
    select row_id as ra, t1.id, t1.eventDate
    from events t1

) as ta
 join
(
     select row_id as rb, t2.id, t2.eventDate
     from events t2
) as tb
on rb = ra+1 and ta.id = tb.id and ta.eventDate = tb.eventDate

【讨论】:

【参考方案4】:

我找到了一种匹配下一行的 eventDate 的方法,但唯一的缺点是它会返回连续日期的数量 - 1 行。但在您的代码中,您可以多循环 1 次。

SET @inc = 0;
SET @innerInc = 1;

SELECT t1.id, t1.eventDate
FROM (
    SELECT id, eventDate, (@inc := @inc + 1) as increment FROM temp
) t1
WHERE t1.eventDate = (
    SELECT t2.eventDate FROM (
        SELECT eventDate, (@innerInc := @innerInc + 1) as increment FROM temp
    ) t2
    WHERE t2.increment = t1.increment
);

这是用于此的 SQLFiddle:Here

【讨论】:

【参考方案5】:

这应该可以通过单表扫描来完成(没有子查询、连接等)

SELECT t.id,t.eventDate
FROM (
    SELECT
        IF(id = @prevID AND eventDate = @prevDate, @counter, @counter := @counter+1) as c,
        @prevID := id as id,
        @prevDate := eventDate as eventDate
    FROM events e
    JOIN (SELECT @counter := 0, @prevID := NULL, @prevDate := NULL) as stuff
    WHERE 1 #or some where condition for events
    ORDER BY row_id ASC
) as t
GROUP BY t.c

【讨论】:

【参考方案6】:

如果不是特别需要 positionally 连续条目,而是如果您按 eventDate 分组并找到具有相同 eventDate 的条目,那么您会想要这些记录,然后以下:

select * 
from Table a
join (select eventDate, count(*)
      from Table
      group by eventDate
      having count(*) > 1) b
on (a.eventDate = b.eventDate)

对数据位置 的任意依赖表明存在您未共享的其他属性,并且正是通过该属性检索和排序记录。如果这样的属性决定了记录的位置,那么正是通过使用 that 属性进行排序或分组,您可以有效地解决这个问题。

【讨论】:

【参考方案7】:

放弃我的自我加入后,我认为您将不得不为每个 sub_query 生成 row_numbers:

select @rn1 := @rn1+1 as ra, t1.id, t1.eventDate
from events t1
join (select @rn1 := 0) r;

然后加入到

select @rn2 := @rn2+1 as rb, t2.id, t2.eventDate
from events t2
join (SELECT @rn2 := 0) r;

所以最后的答案:

select ta.id, ta.eventDate from
(
    select @rn1 := @rn1+1 as ra, t1.id, t1.eventDate
    from events t1
    join (select @rn1 := 0) r
) as ta
 join
(
     select @rn2 := @rn2+1 as rb, t2.id, t2.eventDate
     from events t2
     join (SELECT @rn2 := 0) r
) as tb
on rb = ra+1 and ta.id = tb.id and ta.eventDate = tb.eventDate

结果:

2014 年 2 月 1 日,27 日 23:21:41+0000

2014 年 2 月 27 日 23:25:08+0000

2014 年 2 月 3 日 28 日 15:36:55+0000

2014 年 2 月 4 日,28 日 19:33:31+0000

【讨论】:

以上是关于MySQL - 检查连续列是不是相同并仅显示那些行的主要内容,如果未能解决你的问题,请参考以下文章

隐藏角度Js中的表格行

检查列是不是包含类型字符串(对象)

excel如何检查一列数字是不是连续?

检查mysql中的表中是不是有两行具有相同的元素

PHP和MySQL,快速连续多次检查行的有效方法?

检查列数据类型并仅对 Spark SQL 中的整数和小数执行 SQL