简体   繁体   English

计算mysql中值为1的行之间的行数

[英]count number of rows between rows where value is 1 in mysql

I have the following data:我有以下数据:

client, visit page 2
1,0
2,0
3,1
4,0
5,1
6,0
7,0
8,1

now I want to know how many clients have been since the last client visited page 2. So the outcome would be:现在我想知道自上次客户访问第 2 页以来有多少客户。所以结果是:

client 3, 3; client 5, 2; client 8,3

eventually I only need to numbers of occurrences of the gaps so here I would have as an ultimate answer:最终我只需要出现间隙的次数,所以在这里我将得到一个最终答案:

gap,# occurrences
1,0    
2,1
3,2
4,0

Is this possible in mysql and best would be without a for loop?这在 mysql 中是否可能,最好没有 for 循环?

The data is to large to load it completely in python/php.数据太大,无法在 python/php 中完全加载。 One way would be to use python/php and select all rows where 'visit page 2' is 1 and then do a for loop with a select query with count(rows) between succes n-1 and succes n.一种方法是使用 python/php 并选择“访问页面 2”为 1 的所有行,然后使用在 succes n-1 和 succes n 之间的 count(rows) 选择查询执行 for 循环。 But this takes to much time.但这需要很多时间。

Creates the effect of a row_number with the @rn variable, and maintains the prior row number where vp2=1 occurred in variable @lastWas .使用@rn变量创建row_number的效果,并维护变量@lastWas发生 vp2=1 的先前行号。

The cross-join facilitates not having to do set @rn:= etc stuff at the top.交叉连接有助于不必在顶部设置 @rn:= 等内容。 And that is the sole purpose of it.这就是它的唯一目的。

Note the derived table named inr .请注意名为inr的派生表。 All derived tables require an alias name even if not used explicitly by name.即使没有按名称显式使用,所有派生表也需要别名。 One can run the innards of the derived table separately.可以单独运行派生表的内部结构。 This is used at the beginning of development for a sanity check, then several of the columns there can be ignored in the query on the outside that wraps it.这在开发开始时用于健全性检查,然后在包装它的外部查询中可以忽略其中的几个列。 Certainly as seen here.当然如这里所见。 See inr-only at bottom of answer for a view of just that derived table.请参阅答案底部的inr-only以查看该派生表的视图。

Schema架构

create table x
(   id int auto_increment primary key, 
    client int not null,
    vp2 int not null
);

insert x(client,vp2) values 
(1,0),(2,0),(3,1),(4,0),
(5,1),(6,0),(7,0),(8,1);

Query询问

select client,rn-lastWas as gap from
(   select id,
    client,
    vp2,
    @lastWas as lastWas,
    greatest(@rn:=@rn+1,@lastWas:=if(vp2=1,@rn,@lastWas)) as junk, -- forces recalc immediacy inside greatest() function, caring not at all of results
    @rn as rn
    from x
    cross join (select @rn:=0 as r,@lastWas:=0 as l) as blahJunk
    order by id
) inr
where vp2=1

Results结果

+--------+------+
| client | gap  |
+--------+------+
|      3 |    3 |
|      5 |    2 |
|      8 |    3 |
+--------+------+

Advanced Mysql User Variable Techniques 高级 Mysql 用户变量技术


inr-only:仅inr:

This is a view of just the inr derived table, to help visualize the above.这只是inr派生表的视图,以帮助可视化上述内容。

+----+--------+-----+---------+------+------+
| id | client | vp2 | lastWas | junk | rn   |
+----+--------+-----+---------+------+------+
|  1 |      1 |   0 | 0       | 1    |    1 |
|  2 |      2 |   0 | 0       | 2    |    2 |
|  3 |      3 |   1 | 0       | 3    |    3 |
|  4 |      4 |   0 | 3       | 4    |    4 |
|  5 |      5 |   1 | 3       | 5    |    5 |
|  6 |      6 |   0 | 5       | 6    |    6 |
|  7 |      7 |   0 | 5       | 7    |    7 |
|  8 |      8 |   1 | 5       | 8    |    8 |
+----+--------+-----+---------+------+------+

brownie points section below下面的布朗尼点部分

More schema更多架构

create table bon
(   -- bunch of numbers
    i int not null
);
insert bon(i) values (1),(2),(3),(4);

Brownie points query布朗尼积分查询

select bon.i as gap,ifnull(qry.rowCount,0) as occurrences
from bon
left join
(   select gap,count(*) as rowCount from
    (   select client,rn-lastWas as gap from
        (   select id,
            client,
            vp2,
            @lastWas as lastWas,
            greatest(@rn:=@rn+1,@lastWas:=if(vp2=1,@rn,@lastWas)) as junk, -- forces recalc
            @rn as rn
            from x
            cross join (select @rn:=0 as r,@lastWas:=0 as l) as blahJunk
            order by id
        ) inr -- derived table alias
        where vp2=1
    ) xxx -- every derived table requires an alias
    group by gap
) qry -- derived table alias
on qry.gap=bon.i

results结果

+-----+-------------+
| gap | occurrences |
+-----+-------------+
|   1 |           0 |
|   2 |           1 |
|   3 |           2 |
|   4 |           0 |
+-----+-------------+

One approach, keep a total of the current gap and reset on each visit.一种方法,保持当前的总差距并在每次访问时重置。

select v, count(*) from(
    select client,
           case when visit = 0 then @v := @v + 1
                else @v := @v + 1 end v,
           case when visit = 1 then @v := 0 end gap
    from table join (select @v := 0) v
    order by client
) q
where gap is not null
group by v
;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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