MySql计算包含特定值的行组数

时间:2014-08-13 16:24:47

标签: mysql sql

如何获取状态的“组”数,其中status == 0,不包括启动表的组和跨越< = hour的组? (如果时间限制太难,我们可以选择排除计数< = 40而不是跨越< =小时的组的组,因为每1:30分钟会记录一行。)

例如,如果按状态分组== 0,则以下没有时间约束的SAMPLE表将产生3。

+------+----------+----------+
| id   | status   |time      |
+------+----------+----------+
| 0001 | 1        |11:32:48  |
+------+----------+----------+
| 0002 | 0        |11:30:26  |
+------+----------+----------+
| 0003 | 0        |11:28:54  |
+------+----------+----------+
| 0004 | 1        |11:27:23  |
+------+----------+----------+
| 0005 | 0        |11:25:52  |
+------+----------+----------+
| 0006 | 1        |11:24:20  |
+------+----------+----------+
| 0007 | 1        |11:22:48  |
+------+----------+----------+
| 0008 | 0        |11:21:17  |
+------+----------+----------+
| 0009 | 0        |11:19:45  |
+------+----------+----------+
| 0010 | 0        |11:18:14  |
+------+----------+----------+
| 0011 | 0        |11:16:43  |
+------+----------+----------+
| 0012 | 0        |11:15:11  |
+------+----------+----------+
| 0013 | 0        |11:13:39  |
+------+----------+----------+
| 0002 | 0        |11:12:08  |
+------+----------+----------+
| 0014 | 1        |11:10:37  |
+------+----------+----------+
| 0015 | 1        |11:09:05  |
+------+----------+----------+
| 0016 | 1        |11:07:33  |
+------+----------+----------+
| 0017 | 0        |11:06:02  |
+------+----------+----------+

我能想到的一个解决方案是获取整个表并使用Java生成结果,但我担心这会因为表中有数百万个条目而效率太低。

2 个答案:

答案 0 :(得分:0)

select sum(is_different_from_previous) , status
from (
    select status, 
    (@prevStatus <> status and @prevStatus <> -1) is_different_from_previous,
    @prevStatus := status
    from myTable t1
    cross join (select @prevStatus := -1) t2
    order by t1.time
) t1 group by status

表示特定状态

select * from (
    select sum(is_different_from_previous) , status
    from (
        select status, 
        (@prevStatus <> status and @prevStatus <> -1) is_different_from_previous,
        @prevStatus := status
        from myTable t1
        cross join (select @prevStatus := -1) t2
        order by t1.time
    ) t1 group by status
) t1 where status = 0

修改

仅计算具有特定数量0的组

select count(*) from (
    select * from (
        select status, 
        (@prevStatus <> status and @prevStatus <> -1) is_different_from_previous,
        if(@prevStatus <> status and @prevStatus <> -1,@groupNumber := @groupNumber + 1, @groupNumber) groupNumber,
        @prevStatus := status
        from myTable t1
        cross join (select @prevStatus := -1, @groupNumber := 0) t2
        order by t1.id
    ) t1
    where status = 0
    group by groupNumber
    having count(*) > 4
) t1

http://sqlfiddle.com/#!9/e4a49/23

答案 1 :(得分:0)

尝试以下修改后的查询,该查询比前一个更有效,因为删除了另一个表扫描,我们将数据限制为最后一小时。此外,第一组不计算在内。

编辑:我将JOIN条件更改回st2.id = st1.id+1以满足要求。

select 
  st1.status, 
  count(st1.id)
from sampletable st1
inner join sampletable st2
on (st2.id = st1.id+1 and st2.status <> st1.status)
where st1.status = 0 AND st1.time >= DATE_SUB(NOW(), INTERVAL 1 hour)
group by st1.status;

更新了具有相同ID,状态数据的SQL小提琴演示

SQL Fiddle demo