2014-01-15 8 views
3

Я ищу запрос, способный выбирать из одной таблицы таким образом, чтобы последовательные записи, для которых атрибут равен, свертываются вместе. Подобно группе, но вместо того, чтобы группировать каждое происхождение атрибута вместе, я хочу одну группу для каждого последовательного диапазона.Выбор групп последовательных записей с общим атрибутом?

Пример таблицы:

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

Я не могу использовать хранимые процедуры.

У меня есть неопределенное понятие. Мне нужно, по крайней мере, один уровень вложенности для сортировки таблицы (возможно, больше всего) и, вероятно, придется использовать переменные, но не более того. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

EDIT: Запросы для создания, например:

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.

EDIT: Для того, чтобы получить именно тот результат, на примере:

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 

Be carfeul с переменной group_concat_max_len = 1024 (предельного результата в байтах). Изменение зависит от ваших потребностей.

+0

Спасибо за попытку, но я думаю, что вы неправильно поняли вопрос - мне нужно сгруппировать только последовательные записи или записи, которые находятся рядом друг с другом на столе (после заказа, но он должен работать аналогичным образом для любого существующего набора строк). Таким образом, результат должен содержать несколько групп с одной и той же «групповой» строкой. – Protected

0

Я хотел бы создать временную таблицу со всеми столбцами выше и добавьте 2 колонок ID Int (автоинкрементный для зацикливания) GroupID Int и вставить свои предыдущие результаты в него, затем обновите новый столбец groupid значением int, это создаст группировку, которую вам нужно увидеть ниже.

После того, как вы запустили таблицу temp. Используя цикл while, зацикливайте записи в таблице темпа. Для таблицы temp требуется дополнительный столбец id без пробелов, т. Е. 1,2,3,4,5,6,7,8 .... независимо от ваших результатов.

в цикле проверить, если группа этой строки = последняя группа строк, если да, установите groupid для groupid else, чтобы установить на groupid + 1. и сбросить groupid как groupid = groupid + 1.

поэтому для вашей группы eaxample начинается с 0. затем читает первую строку и устанавливает groupid в groupid (0). затем прочитайте строку 2, проверьте, если group = last rows groupd> yes, она делает это row> group id = groupid.

прочитанная строка 3 выполняет групповое сопоставление последней группы строк> no> groupid = groupid + 1, а затем устанавливает groupid в groupid.

проверка 4,5,6,7 и т. Д.

После того, как все сделано, просто сгруппируйте новый столбец, и вы получите желаемые результаты. Надеюсь это поможет. Я не вижу другого способа сделать это без цикла

Смежные вопросы