Mysql - how to group column values ββinto min-max ranges?
Can the values ββof another column be grouped in multiple range definitions?
Here's an example table:
mysql> select * from t;
+------+------+
| x | y |
+------+------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
| 6 | 2 |
| 7 | 1 |
| 8 | 1 |
| 9 | 1 |
+------+------+
I want to select the following information: y=1
has a range of x: 1-3, 7-9
, y=2
has a range of: 4-6
.
Definition and data:
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);
source to share
If x is a contiguous sequence (no spaces), you can do this:
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
If it doesn't, you can do something like this:
SELECT a.y
, a.x start
, MIN(c.x) end
FROM (SELECT *,@a:=@a+1 rank FROM t,(SELECT @a:=0) vars ORDER BY x) a
LEFT
JOIN (SELECT *,@b:=@b+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:=@c+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:=@d+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
However, both of these queries will be slow for large datasets. However, the idea behind the second solution can be adapted for cases where performance is an issue - well, like cars10's solution.
source to share
Try the following:
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 @g=@c AND x=@l+1
THEN @g ELSE @c:=@g:=@g+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
Variables used :
@g group counter
@c current x value
@l previous ('last') x value
I also fixed individual items for each group issue.
See here for working scripts: http://www.sqlfiddle.com/#!9/cc836/2
source to share