选择具有公共属性的连续记录组?

时间:2014-01-15 10:19:58

标签: mysql sql

我正在寻找能够从单个表中进行选择的查询,使得属性相等的连续记录被折叠在一起。与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');

3 个答案:

答案 0 :(得分: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进行分组,这可以区分每个连续的组,即使它们具有相同的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

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

注意变量group_concat_max_len = 1024(结果限制,以字节为单位)。根据您的需求进行更改。

答案 2 :(得分:0)

我会创建一个包含上面所有列的临时表,并添加2列id int(自动增量用于循环)groupid int并将上面的结果插入其中,然后使用int值更新新的groupid列,这将创建分组你需要看下面..

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

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

因此,对于您的eaxample,groupid以0开头,然后读取第一行并将groupid设置为groupid(0)。然后读第2行检查group = last rows groupd>是的,所以行> group id = groupid。

读取第3行与最后一行组匹配>没有> groupid = groupid + 1然后将groupid设置为groupid。

检查4,5,6,7等。

完成所有操作后,只需按新列分组即可获得所需的结果。希望这可以帮助。在没有循环

的情况下,我无法看到另一种方法
相关问题