计算mysql

时间:2015-10-26 22:19:22

标签: 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,然后使用带有成功n-1和成功n之间的count(行)的select查询执行for循环。但这需要很长时间。

2 个答案:

答案 0 :(得分:1)

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

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

请注意名为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 |
+--------+------+

Advanced Mysql User Variable Techniques

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 |
+-----+-------------+

答案 1 :(得分: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
;