2015-06-12 1 views
3

Могу ли я группировать значения другого столбца в определения нескольких диапазонов?Mysql - как группировать значения столбца в диапазоны min-max?

Вот пример таблицы:

mysql> select * from t; 
+------+------+ 
| x | y | 
+------+------+ 
| 1 | 1 | 
| 2 | 1 | 
| 3 | 1 | 
| 4 | 2 | 
| 5 | 2 | 
| 6 | 2 | 
| 7 | 1 | 
| 8 | 1 | 
| 9 | 1 | 
+------+------+ 

Я хочу, чтобы выбрать следующую информацию: y=1 имеет диапазоны х: 1-3, 7-9, y=2 имеет диапазоны: 4-6.

Определение и данные:

create table t (x int, y int); 
insert into t(x,y) values (1,1),(2,1),(3,1),(4,2),(5,2),(6,2),(7,1),(8,1),(9,1); 
+0

Итак, вы хотите найти начало и конец последовательности. – Strawberry

+0

@Strawberry yes – Fluffy

+0

Может ли x иметь пробелы? – Strawberry

ответ

1

Если х представляет собой непрерывную последовательность (без пробелов), то вы можете сделать это:

SELECT a.y 
    , a start 
    , MIN(c.x) end 
    FROM t a 
    LEFT 
    JOIN t b 
    ON b.y = x.y 
    AND b.x = a.x - 1 
    LEFT 
    JOIN tbl c 
    ON c.y = a.y 
    AND c.x >= a.x 
    LEFT 
    JOIN t d 
    ON d.y = a.y 
    AND d.x = c.x + 1 
WHERE b.x IS NULL 
    AND c.x IS NOT NULL 
    AND d.x IS NULL 
GROUP 
    BY a.y,a.x; 

http://www.sqlfiddle.com/#!9/26aef/33

Если это не то может сделать что-то вроде этого:

SELECT a.y 
    , a.x start 
    , MIN(c.x) end 
    FROM (SELECT *,@a:[email protected]+1 rank FROM t,(SELECT @a:=0) vars ORDER BY x) a 
    LEFT 
    JOIN (SELECT *,@b:[email protected]+1 rank FROM t,(SELECT @b:=0) vars ORDER BY x) b 
    ON b.y = a.y 
    AND b.rank = a.rank - 1 
    LEFT 
    JOIN (SELECT *,@c:[email protected]+1 rank FROM t,(SELECT @c:=0) vars ORDER BY x) c 
    ON c.y = a.y 
    AND c.rank >= a.rank 
    LEFT 
    JOIN (SELECT *,@d:[email protected]+1 rank FROM t,(SELECT @d:=0) vars ORDER BY x) d 
    ON d.y = a.y 
    AND d.rank = c.rank + 1 
WHERE b.x IS NULL 
    AND c.x IS NOT NULL 
    AND d.x IS NULL 
GROUP 
    BY a.y,a.x; 

http://www.sqlfiddle.com/#!9/26aef/54

Однако оба этих запроса будут медленными для больших наборов данных. Тем не менее, идея, содержащаяся во втором решении, может быть адаптирована для случаев, когда производительность является проблемой - ну, как и решение cars10.

1

Попробуйте это:

SELECT y,group_concat(xr) FROM (
SELECT y, 
    CASE WHEN min(x)=max(x) THEN CAST(min(x) as char(8)) 
     ELSE concat(CAST(min(x) AS char(8)),'-',CAST(max(x) AS char(8))) 
    END xr, g FROM (
    SELECT y,x, CASE WHEN @[email protected] AND [email protected]+1 
        THEN @g ELSE @c:[email protected]:[email protected]+1 END g , 
     @l:=x lastx 
    FROM tab,(SELECT @g:=0, @c:=-1, @l=-1) vars 
    ORDER BY y,x 
) grp1 
GROUP BY y,g 
) grp2 GROUP BY y 

переменные, используемые:

@g group counter 
@c current x value 
@l previous ('last') x value 

Я также установил отдельные элементы в каждой группе проблем.

Смотрите здесь для рабочего скрипкой: http://www.sqlfiddle.com/#!9/cc836/2

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