繁体   English   中英

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

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

我有以下数据:

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

现在我想知道自上次客户访问第 2 页以来有多少客户。所以结果是:

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

最终我只需要出现间隙的次数,所以在这里我将得到一个最终答案:

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

这在 mysql 中是否可能,最好没有 for 循环?

数据太大,无法在 python/php 中完全加载。 一种方法是使用 python/php 并选择“访问页面 2”为 1 的所有行,然后使用在 succes n-1 和 succes n 之间的 count(rows) 选择查询执行 for 循环。 但这需要很多时间。

使用@rn变量创建row_number的效果,并维护变量@lastWas发生 vp2=1 的先前行号。

交叉连接有助于不必在顶部设置 @rn:= 等内容。 这就是它的唯一目的。

请注意名为inr的派生表。 即使没有按名称显式使用,所有派生表也需要别名。 可以单独运行派生表的内部结构。 这在开发开始时用于健全性检查,然后在包装它的外部查询中可以忽略其中的几个列。 当然如这里所见。 请参阅答案底部的inr-only以查看该派生表的视图。

架构

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);

询问

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

结果

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

高级 Mysql 用户变量技术


仅inr:

这只是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 |
+----+--------+-----+---------+------+------+

下面的布朗尼点部分

更多架构

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

布朗尼积分查询

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

结果

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

一种方法,保持当前的总差距并在每次访问时重置。

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