简体   繁体   中英

Count rows until value in column changes in MySQL

I have same problem like in this question Count rows until value in column changes mysql But although the issue was resolved I not understand this query. Because I have low reputation points I can't leave comment there and must open new question.

My example:

mysql> select * from example;
+----+-------+------+
| id | name  | succ |
+----+-------+------+
|  1 | peter |    1 |
|  2 | bob   |    1 |
|  3 | peter |    0 |
|  4 | peter |    0 |
|  5 | nick  |    1 |
|  6 | bob   |    0 |
|  7 | peter |    1 |
|  8 | bob   |    0 |
|  9 | peter |    1 |
| 10 | peter |    1 |
+----+-------+------+
10 rows in set (0.00 sec)

I want to count successive true values for peter (descending id, and results must be 3), I know how to set query like this :

mysql> select count(succ) 
       from example 
       where id > (select max(id) from example where succ = 0);
+-------------+
| count(succ) |
+-------------+
|           2 |
+-------------+
1 row in set (0.00 sec)

But how to get results just for peter, and if it is possible to get results grouped by name, like this:

    +--------+------+
    |name    | succ |
    +--------+------+
    |  peter | 3    |
    |  bob   | 0    |
    |  nick  | 1    |
    +--------+------+

One way to solve this is with a self join. Using an outer join you exclude the rows that have a matching row with a higher id value and succ = 0 , and then count the rows with succ = 1 using SUM() and CASE .

Here's the query for your example:

select e1.name, 
  sum(case when e1.succ = 1 then 1 else 0 end) as succ
from example e1 
left outer join example e2 on e2.id > e1.id 
  and e2.name = e1.name 
  and e2.succ = 0
where e2.id is null
group by e1.name

Use variables to count consecutive successes (re-starting when seeing a failure), and join with a query which selects highest id per name (somewhat similar to McNets's answer)

SELECT a.name, a.count FROM (    
  SELECT  e1.id, e1.name, e1.succ,
    @count_success := IF (@prev_name = e1.name AND e1.succ = 1, @count_success + 1, e1.succ) AS `count`,
    @prev_name := e1.name AS `prev_name`
  FROM `example` e1, (SELECT @count_success :=0, @prev_name := NULL) init
  ORDER BY e1.name, e1.id ) `a` 
  JOIN (SELECT MAX(id) AS `max` FROM `example` GROUP BY `name`) `b` ON a.id = b.max

if you need the count of records

select name, count(succ) from example group by name

or if you need the sum of the succ of every person you can use

select name, sum(succ) from example group by name 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM