我们说我有一张桌子
+----+------------+
| id | condition |
+----+------------+
| 1 | open |
+----+------------+
| 2 | content |
+----+------------+
| 3 | content |
+----+------------+
| 4 | close |
+----+------------+
| 5 | nocontentx |
+----+------------+
| 6 | nocontenty |
+----+------------+
| 7 | open |
+----+------------+
| 8 | content |
+----+------------+
| 9 | close |
+----+------------+
| 10 | nocontentz |
+----+------------+
| 11 | open |
+----+------------+
| 12 | content |
+----+------------+
并希望获得一个新表格,我在其中获取" close
"之间的值的ID(第一个和最后一个);和" open
"。请注意,这两个条件之间的值是动态的(我无法按"nocontent"whatever
搜索)
比如我得到这张表:
+----+----------+--------+
| id | start_id | end_id |
+----+----------+--------+
| 1 | 5 | 6 |
+----+----------+--------+
| 2 | 10 | 10 |
+----+----------+--------+
提前致谢!
答案 0 :(得分:5)
您可以使用相关子查询执行此操作:
select (@rn := @rn + 1) as id,
id as startid,
(select id
from atable a2
where a2.id > a.id and
a2.condition = 'close'
order by a2.id asc
limit 1
) as end_id
from atable a cross join
(select @rn := 0) vars
where a.condition = 'open';
工作的SQL小提琴是here。
注意这也会返回第三个open
。如果您不想要它,请将having end_id is not null
添加到查询的末尾。
编辑:
如果你知道id是顺序的,你可以在上面的查询中添加和减去1:
select (@rn := @rn + 1) as id,
id+1 as startid,
(select id
from atable a2
where a2.id > a.id and
a2.condition = 'open'
order by a2.id asc
limit 1
) - 1 as end_id
from atable a cross join
(select @rn := 0) vars
where a.condition = 'close';
您也可以通过不同的方式执行此操作,即通过计算任何给定行之前打开和关闭的数量并将其用作组标识符。数据的结构方式,每个其他组都是您正在寻找的:
select grp, min(id), max(id)
from (select t.*,
(select sum(t2.condition in ('open', 'close'))
from t t2
where t2.id <= t.id
) as grp
from t
) t
where t.condition not in ('open', 'close') and
grp % 2 = 0
group by grp;