2014-01-15 49 views
3

我正在查找能够从单个表中选择的查询,以便将属性相同的连续记录合并在一起。与group by类似,但不是将每个属性的每次出现分组在一起,而是希望每个连续范围都有一个组。选择具有共同属性的连续记录组?

实施例的表:

+-----+-----+ 
|order|group| 
+-----+-----+ 
|1 |aaa | 
+-----+-----+ 
|2 |aaa | 
+-----+-----+ 
|3 |bbb | 
+-----+-----+ 
|4 |aaa | 
+-----+-----+ 
|5 |aaa | 
+-----+-----+ 
|6 |aaa | 
+-----+-----+ 
|7 |ccc | 
+-----+-----+ 
|8 |aaa | 
+-----+-----+ 

实施例所期望的结果:

+-----+-------------------+ 
|group|group_concat(order)| 
+-----+-------------------+ 
|aaa |1,2    | 
+-----+-------------------+ 
|bbb |3     | 
+-----+-------------------+ 
|aaa |4,5,6    | 
+-----+-------------------+ 
|ccc |7     | 
+-----+-------------------+ 
|aaa |8     | 
+-----+-------------------+ 

我不能使用存储的过程。

我有一个模糊的概念,我将需要至少一个级别的表进行排序的嵌套(可能更多),可能不得不使用变量,但不超过。如果您需要更多详细信息,请告诉我。

编辑:用于创建例如查询:

create temporary table tab (
    ord int, 
    grp varchar(8) 
); 

insert into tab (ord, grp) values 
(1, 'aaa'), 
(2, 'aaa'), 
(3, 'bbb'), 
(4, 'aaa'), 
(5, 'aaa'), 
(6, 'aaa'), 
(7, 'ccc'), 
(8, 'aaa'); 

回答

1

你可以试试吗?你可以在这里测试http://www.sqlfiddle.com/#!2/57967/12

Select grp_new, group_concat(ord) 
From (
    Select ord, if(grp = @prev, @seq, @seq := @seq + 1) as seq, 
    if(grp = @prev, grp, @prev := grp) as grp_new 
    From tab, (SELECT @seq := 0, @prev := '') AS init 
    Order by ord 
) x 
Group by grp_new, seq; 

关键的想法是为相同的连续组生成相同的seq,如下所示。

Select 
    ord, if(grp = @prev, @seq, @seq := @seq + 1) as seq, 
    if(grp = @prev, grp, @prev := grp) as grp_new 
From tab, (SELECT @seq := 0, @prev := '') AS init 
Order by ord 

然后最后分组GROUP BY grp, seq可以differenciate每个连续的群体,即使它们具有相同的grp

编辑:在本例中得到完全的结果:

Select grp_new, group_concat(ord order by ord) 
From (
    Select ord, if(grp = @prev, @seq, @seq := @seq + 1) as seq, 
    if(grp = @prev, grp, @prev := grp) as grp_new 
    From tab, (SELECT @seq := 0, @prev := '') AS init 
    Order by ord 
) x 
Group by seq 
+0

每个字符串只有一个组,恐怕。只要你通过grp对外部查询进行分组,它肯定会以这种方式失败。 – Protected

+0

@保护是的。有一些错误。你能试试我的查询吗? –

+0

很好,谢谢! – Protected

0

使用:

select pquery.group, GROUP_CONCAT(pquery.order separator ', ') as order FROM 
( select t.*, @lastSeq := if(t.group != @lastGroup         
         , 0, @lastSeq + 1) 
       as groupSeq, 
    @lastGroup := t.group, 
    @cont := if(@lastSeq =0, @cont + 1, @cont) as counter, 
    @cgroup := concat(@cont,t.group) as cgroup 
    from t, (select @lastGroup := '', 
    @lastSeq := 0, @cont :=0) sqlVars 
) pquery 
group by pquery.cgroup 

成为carfeul与可变group_concat_max_len = 1024(字节结果极限)。根据您的需求进行更改。

+0

谢谢你的尝试,但我认为你误解了这个问题 - 我只需要分组连续的记录,或在表上彼此相邻的记录(订购后,但它应该以任何预先存在的行的类似方式工作)。所以结果应该允许多个组具有相同的“组”字符串。 – Protected

0

我会创建一个临时表上面的所有列,并添加2列ID INT(自动增量的循环)的groupid int和插入您的上述结果然后用一个int值更新新的groupid列,这将创建你需要的分组见下面..

一旦你有临时表填充使用while循环,循环记录在临时表中。临时表需要一个递增的ID列,没有间隙,即1,2,3,4,5,6,7,8 ....无论结果如何。

循环内部检查此行的组=最后一行组是否将组ID设置为组别ID否则设置为组ID + 1。并将groupid重置为groupid = groupid + 1。

因此,您的eaxample从0开始。然后读取第一行并将groupid设置为groupid(0)。然后读取第2行检查是否group =最后一行groupd> yes它这样做row> group id = groupid。

读取的行3不匹配最后一行组> no> groupid = groupid + 1然后将groupid设置为groupid。

检查4,5,6,7等

一旦所有完成,然后只是由新列组合,你会得到你想要的结果。希望这可以帮助。我不能看到任何其他的方式做这个没有循环