在 MySQL 中连续分组值并为这些组添加一个 id
Posted
技术标签:
【中文标题】在 MySQL 中连续分组值并为这些组添加一个 id【英文标题】:Group consecutively values in MySQL and add an id to such groups 【发布时间】:2015-08-04 16:25:33 【问题描述】:我有一个简单的表,我需要识别四行的组(这些组不是连续的),但每行的每一行的值都有一个 +1。例如:
---------------------- |语言 |编号 | ---------------------- | C | 16 | | C++ | 17 | |爪哇 | 18 | |蟒蛇 | 19 | | html | 65 | | javascript | 66 | | php | 67 | |珀尔 | 68 | ----------------------我想添加一个表示组或集合的列,如何使用 mysql 获得此输出?:
---------------------------- |语言 |编号 |设置 | ---------------------------- | C | 16 | 1 | | C++ | 17 | 1 | |爪哇 | 18 | 1 | |蟒蛇 | 19 | 1 | | HTML | 65 | 2 | | JavaScript | 66 | 2 | | PHP | 67 | 2 | |珀尔 | 68 | 2 | ----------------------------请注意,在此示例中只有 2 个集合(可能是 1 个或多个集合)并且它们不是从 16 开始的(这些值是未知的,但限制是每行的每个 id 值都有这种形式n、n+1、n+2 和 n+3)。
我一直在调查 Gaps & Islands 问题,但不知道如何使用他们的解决方案来解决它。我也在***上搜索,但我发现最接近的问题是How to find gaps in sequential numbering in mysql?
谢谢
【问题讨论】:
您是否需要持续执行此查询,或者这是您将用于填充set
值的一次性查询?
此查询应与动态数据多次使用(4 行组的值可以更改,但此类组不相关,即没有 2 个组涵盖从 1 到 8 id 值)。
【参考方案1】:
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
FIDDLE
【讨论】:
此查询如何识别 4 个连续记录的组? @GiorgosBetsos 相同,它标识 3 或 2 或 10 条连续记录。它检查下一条记录是否具有前一条的 id +1。 我认为 OP 希望 only 组返回 4 个连续记录,而其他所有记录都被过滤掉。 @GiorgosBetsos 我认为这只是示例数据,但这种情况很容易通过每组的行号来修复。【参考方案2】:select language,
@n:=if(@m+1=id, @n, @n+1) `set`,
(@m:=id) id
from t1,
(select @n:=0) n,
(select @m:=0) m
Demo on sqlfiddle
【讨论】:
没有 ORDER BY 的结果不能保证 从我看不到的问题条件来看,下一组是否不会从1开始:)【参考方案3】:您可以使用以下查询:
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条连续记录的孤岛,并且只返回那里的记录。考虑不同数量的连续记录很容易修改。
还请注意IF
条件的用法:它保证@rn1
被首先 初始化并然后 用于计算grp
字段。
Demo here
【讨论】:
如果我插入更多的值只返回 1 和 3 的 id:sqlfiddle.com/#!9/c4b15/1/0 @Wronski 我的解决方案是过滤掉所有的记录孤岛,这些记录的数量与 4 不同。我以为这是OP的要求。以上是关于在 MySQL 中连续分组值并为这些组添加一个 id的主要内容,如果未能解决你的问题,请参考以下文章