Количество последовательных ненулевых значений - PullRequest
2 голосов
/ 24 августа 2009

Количество должно быть 3 и 1 в следующем запросе. Счет должен состоять из очков, заработанных последовательно. Поэтому, как только пользователь не заработает ни одного очка, счет возобновляется.

mysql> select name, count(*) from sortest group by name, (points = 0) OR (points is NULL)  having name= 'john';
+------+----------+
| name | count(*) |
+------+----------+
| john |        4 |
| john |        2 |
+------+----------+
2 rows in set (0.00 sec)

mysql> select * from sortest;
+----+------+--------+
| id | name | points |
+----+------+--------+
|  1 | john |     12 |
|  2 | john |     23 |
|  3 | john |     43 |
|  4 | hari |   NULL |
|  5 | hari |     56 |
|  6 | john |   NULL |
|  7 | hari |      0 |
|  8 | john |     44 |
|  9 | john |      0 |
| 10 | hari |     43 |
| 11 | hari |     44 |
| 12 | hari |     78 |
| 13 | hari |      0 |
+----+------+--------+
13 rows in set (0.00 sec)

mysql> show create table sortest\G
*************************** 1. row ***************************
       Table: sortest
Create Table: CREATE TABLE `sortest` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(100) default NULL,
  `points` int(11) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=14 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

В этом случае счет Джона должен быть 5, 1 и 2

5 и 1, потому что он заканчивается 0 или NULL и 2, потому что он еще не закрыт 0 или NULL

mysql> select * from sortest;
+----+------+--------+
| id | name | points |
+----+------+--------+
|  1 | john |     12 |
|  2 | john |     23 |
|  3 | john |     43 |
|  4 | hari |   NULL |
|  5 | hari |     56 |
|  6 | john |   NULL |
|  7 | hari |      0 |
|  8 | john |     44 |
|  9 | john |      0 |
| 10 | hari |     43 |
| 11 | hari |     44 |
| 12 | hari |     78 |
| 13 | hari |      0 |
| 14 | john |     55 |
| 15 | john |     95 |
+----+------+--------+
15 rows in set (0.00 sec)

mysql> select name, count(*) from sortest group by name, (points = 0) OR (points is NULL)  having name= 'john';
+------+----------+
| name | count(*) |
+------+----------+
| john |        6 |
| john |        2 |
+------+----------+
2 rows in set (0.00 sec)

Ответы [ 3 ]

2 голосов
/ 24 августа 2009

Почему счет должен быть 3 и 1? Ваш запрос группируется по:

  1. имя
  2. (баллов = 0 ИЛИ баллов НУЛЬ)

Есть две строки, где name=john и (points = 0 OR points IS NULL), а четыре другие строки, где name=john.

Итак, ваш запрос работает так, как вы его описали. Что вы в конечном итоге пытаетесь достичь?

1 голос
/ 24 августа 2009

Чтобы выбрать максимальную выигрышную серию:

SELECT  name, MAX(cnt)
FROM    (
        SELECT  name, COUNT(*) AS cnt
        FROM    (
                SELECT  sortest.*,
                        @r := @r + ((COALESCE(@name, name) <> name) OR (COALESCE(points, 0) = 0)) AS series,
                        @name := name
                FROM    (
                        SELECT  @name := NULL,
                                @r := 0
                        ) vars, sortest
                ORDER BY
                        name, id
                ) q
        WHERE   points > 0
        GROUP BY
                name, series
        ) q2
GROUP BY
        name

Чтобы выбрать все серии побед:

SELECT  name, COUNT(*) AS cnt
FROM    (
        SELECT  sortest.*,
                @r := @r + ((COALESCE(@name, name) <> name) OR (COALESCE(points, 0) = 0)) AS series,
                @name := name
        FROM    (
                SELECT  @name := NULL,
                        @r := 0
                ) vars, sortest
        ORDER BY
                name, id
        ) q
WHERE   points > 0
GROUP BY
        name, series
1 голос
/ 24 августа 2009

Во-первых, то, что вы спрашиваете, немного несвязно. Видите ли, нет порядка порядка без предложения order by. Но я предполагаю, что вы хотите получить количество всего перед строкой null, упорядоченной по id.

Во-вторых, здесь идет:

select
    a.name,
    (select count(*) from sortest where id < a.id and
        id > b.priorId) as count
from
    sortest a
    inner join (select id,
                    (select coalesce(max(id), 0) 
                     from sortest where points is null and id < s1.id) as priorId
                from sortest s1 where points is null
                union
                select max(id) as id,
                    (select coalesce(max(id), 0) 
                     from sortest where points is null and id < s1.id) as priorId
                from sortest s2group by name) b on
        a.id = b.id

Это немного сумбурно и запутанно, но это даст вам то, что вы хотите.

...