在 MySQL 中对值进行连续分组,并向这些组添加一个 id
Group consecutively values in MySQL and add an id to such groups
我有一个简单的 table,我需要确定四行的组(这些组不是连续的),但每一行的每一行的值都有一个 +1。例如:
----------------------
| language | id |
----------------------
| C | 16 |
| C++ | 17 |
| Java | 18 |
| Python | 19 |
| HTML | 65 |
| JavaScript | 66 |
| PHP | 67 |
| Perl | 68 |
----------------------
我想添加一个指示组或集合的列,如何使用 MySQL 获得此输出?:
----------------------------
| language | id | set |
----------------------------
| C | 16 | 1 |
| C++ | 17 | 1 |
| Java | 18 | 1 |
| Python | 19 | 1 |
| HTML | 65 | 2 |
| JavaScript | 66 | 2 |
| PHP | 67 | 2 |
| Perl | 68 | 2 |
----------------------------
注意这个例子中只有2组(可以是1组或多组)而且不是从16开始的(不知道这样的值,但限制是每行的每个id值都有这种形式 n, n+1, n+2 和 n+3).
我一直在调查差距和孤岛问题,但没有想出如何使用他们的解决方案来解决它。我也在 Whosebug 上搜索,但我发现最接近的问题是 How to find gaps in sequential numbering in mysql?
谢谢
SELECT language,id,g
FROM (
SELECT language,id,
CASE WHEN id=@lastid+1 THEN @n ELSE @n:=@n+1 END AS g,
@lastid := id As b
FROM
t, (SELECT @n:=0) r
ORDER BY
id
) s
编辑
如果您只想每组 4 个,请添加行号变量:
SELECT language,id,g,rn
FROM (
SELECT language,id,
CASE WHEN id=@lastid+1 THEN @n ELSE @n:=@n+1 END AS g,
@rn := IF(@lastid+1 = id, @rn + 1, 1) AS rn,
@lastid := id As dt
FROM
t, (SELECT @n:=0) r
ORDER BY
id
) s
Where rn <=4
select language,
@n:=if(@m+1=id, @n, @n+1) `set`,
(@m:=id) id
from t1,
(select @n:=0) n,
(select @m:=0) m
您可以使用以下查询:
SELECT l.*, s.rn
FROM languages AS l
INNER JOIN (
SELECT minID, @rn2:=@rn2+1 AS rn
FROM (
SELECT MIN(id) AS minID
FROM (
SELECT id,
id - IF (true, @rn1:=@rn1+1, 0) AS grp
FROM languages
CROSS JOIN (SELECT @rn1:=0) AS var1
ORDER BY id) t
GROUP BY grp
HAVING COUNT(grp) = 4 ) u
CROSS JOIN (SELECT @rn2:=0) AS var2
) s ON l.id BETWEEN minID AND minID + 3
以上查询确定了 正好 4 个连续记录的岛屿,并且 returns 只有这些记录。它很容易修改以说明不同数量的连续记录。
请注意 IF
条件的用法:它保证 @rn1
是 first 初始化和 then 用于计算 grp
字段。
我有一个简单的 table,我需要确定四行的组(这些组不是连续的),但每一行的每一行的值都有一个 +1。例如:
---------------------- | language | id | ---------------------- | C | 16 | | C++ | 17 | | Java | 18 | | Python | 19 | | HTML | 65 | | JavaScript | 66 | | PHP | 67 | | Perl | 68 | ----------------------
我想添加一个指示组或集合的列,如何使用 MySQL 获得此输出?:
---------------------------- | language | id | set | ---------------------------- | C | 16 | 1 | | C++ | 17 | 1 | | Java | 18 | 1 | | Python | 19 | 1 | | HTML | 65 | 2 | | JavaScript | 66 | 2 | | PHP | 67 | 2 | | Perl | 68 | 2 | ----------------------------
注意这个例子中只有2组(可以是1组或多组)而且不是从16开始的(不知道这样的值,但限制是每行的每个id值都有这种形式 n, n+1, n+2 和 n+3).
我一直在调查差距和孤岛问题,但没有想出如何使用他们的解决方案来解决它。我也在 Whosebug 上搜索,但我发现最接近的问题是 How to find gaps in sequential numbering in mysql?
谢谢
SELECT language,id,g
FROM (
SELECT language,id,
CASE WHEN id=@lastid+1 THEN @n ELSE @n:=@n+1 END AS g,
@lastid := id As b
FROM
t, (SELECT @n:=0) r
ORDER BY
id
) s
编辑
如果您只想每组 4 个,请添加行号变量:
SELECT language,id,g,rn
FROM (
SELECT language,id,
CASE WHEN id=@lastid+1 THEN @n ELSE @n:=@n+1 END AS g,
@rn := IF(@lastid+1 = id, @rn + 1, 1) AS rn,
@lastid := id As dt
FROM
t, (SELECT @n:=0) r
ORDER BY
id
) s
Where rn <=4
select language,
@n:=if(@m+1=id, @n, @n+1) `set`,
(@m:=id) id
from t1,
(select @n:=0) n,
(select @m:=0) m
您可以使用以下查询:
SELECT l.*, s.rn
FROM languages AS l
INNER JOIN (
SELECT minID, @rn2:=@rn2+1 AS rn
FROM (
SELECT MIN(id) AS minID
FROM (
SELECT id,
id - IF (true, @rn1:=@rn1+1, 0) AS grp
FROM languages
CROSS JOIN (SELECT @rn1:=0) AS var1
ORDER BY id) t
GROUP BY grp
HAVING COUNT(grp) = 4 ) u
CROSS JOIN (SELECT @rn2:=0) AS var2
) s ON l.id BETWEEN minID AND minID + 3
以上查询确定了 正好 4 个连续记录的岛屿,并且 returns 只有这些记录。它很容易修改以说明不同数量的连续记录。
请注意 IF
条件的用法:它保证 @rn1
是 first 初始化和 then 用于计算 grp
字段。