问题是,您想根据列的特定顺序进行分组,而不是列页面。
这是一个解决方法:
CREATE TABLE Table1
(id int auto_increment, `page` varchar(1), `time` int, primary key (id))
;
INSERT INTO Table1
(`page`, `time`)
VALUES
('x', 0),
('x', 1),
('x', 2),
('y', 0),
('y', 1),
('x', 0),
('x', 1),
('x', 2),
('x', 3),
('z', 0),
('z', 1),
('z', 2),
('z', 3)
;
select page, max(time) from (
select
t.*
, IF(@prev != page, @counter := @counter + 1, @counter) as my_groups
, @prev:=page
from
Table1 t
, (select @prev:=NULL, @counter:=0) v
order by id
) sq
group by my_groups
看到它在 sqlfiddle 中现场工作。
请注意,我介绍了专栏id
。它只是一个有助于保证订单的列。在数据库中没有第一行或最后一行。当您仅从表中选择时,插入行的顺序不是保证顺序。
解释:
这里
Table1 t
, (select @prev:=NULL, @counter:=0) v
我们在查询中初始化我们的变量。这和写作一样
SET @prev:=NULL;
SET @counter:=0;
SELECT ... FROM Table1 ORDER BY whatever...
现在在子查询的 SELECT 部分
, IF(@prev != page, @counter := @counter + 1, @counter) as my_groups
, @prev:=page
这 2 行按照它们的写入顺序很重要。第二行将读取行的值分配给变量@prev。在第一行中,我们检查 @prev 是否与 SELECT 读取的行不同。如果是,我们将计数器变量 @counter 增加 1,如果不是,我们保持原样。
子查询(稍作修改以使其更清楚发生了什么)
select
IF(@prev != page, @counter := @counter + 1, @counter) as my_groups
, page
, @prev
, @prev:=page
, time
from
Table1 t
, (select @prev:=NULL, @counter:=0) v
order by id
然后返回此结果:
| MY_GROUPS | PAGE | @PREV | @PREV:=PAGE | TIME |
--------------------------------------------------
| 0 | x | (null) | x | 0 |
| 0 | x | x | x | 1 |
| 0 | x | x | x | 2 |
| 1 | y | x | y | 0 |
| 1 | y | y | y | 1 |
| 2 | x | y | x | 0 |
| 2 | x | x | x | 1 |
| 2 | x | x | x | 2 |
| 2 | x | x | x | 3 |
| 3 | z | x | z | 0 |
| 3 | z | z | z | 1 |
| 3 | z | z | z | 2 |
| 3 | z | z | z | 3 |
外部查询很简单。我们按列分组my_groups
(我们用它为这一行起别名)
IF(@prev != page, @counter := @counter + 1, @counter) as my_groups
对于每个组,我们返回页面和最长时间。
希望现在一切都清楚了。不过,如果不是这种情况,请随时问:)