MySQL:选择后跟特定行的行

时间:2014-11-10 12:04:40

标签: php mysql select

如果在下面的示例表中有两个跟随和连接事件的值为110并且所有具有相同id的事件时,如何选择具有值105的事件category

通过连接值为110的事件,我的意思是在110个具有相同类别的事件之间没有其他事件(如106或112)。

 id     category    event
  8     100         110
 12     100         105
 19     101         112
 22     100         106
 31     100         110
 42     101         106
 121    100         110
 254    100         104

在上面的示例中,id 12将被返回,因为它是事先105事件到连接110事件的行31和121,它们之间没有任何其他事件,并且所有事件都在相同的类别100中。

只要有效,查询的效率,或者应该组合多少查询并不重要。

更新: 表达问题的简单方法:返回在同一类别中至少存在两个相邻的110s的所有105个

2 个答案:

答案 0 :(得分:1)

如果我理解正确,您需要event为105的行,而id的两行event的行select t.* from sample t where t.event = 105 and (select count(*) from sample t2 where t2.category = t.category and t2.id > t.category and t2.category = 110 ) = 2; 等于110.如果是这样的话:

group_concat()

编辑:

我认为你可以用select t.category from sample t group by t.category where concat('|', group_concat(event order by id separator '||'), '"') like '%|105|%|110|110|%)

做你想做的事
{{1}}

然后您可以加入以获取事件为105的详细信息。

答案 1 :(得分:1)

由于缺乏分析函数LAG和LEAD,在MySQL中有点笨拙。

select distinct e105.id
from events e105
join
(
  -- all 110 that are directly followed by  a110
  select just_before.id, just_before.category
  from
  (
    -- all 110 and their direct predecessor
    select events.id, min(before.id) as just_before_id
    from events
    left join events before on before.category = events.category and before.id < events.id
    where events.event = 110
    group by events.id
  ) event110
  join events just_before on just_before.id = event110.just_before_id and just_before.event = 110
) e110 on e110.category = e105.category and e110.id > e105.id
where events.event = 105
and not exists
(
  -- a later occuring 105 still bevor the 110 pair
  select *
  from events bad105
  where bad105.category = e105.category and bad105.id > e105.id and bad105.id < e110.id
);

编辑1:我注意到,你可能需要DISTINCT用于案例105-110-110-112-110-110。两个110对将导致相同的105被发现两次。因为这个原因,我已经在上面添加了DISTICT。我还为要选择的ID添加了限定符e105,因为它丢失了。

编辑2:我也注意到你不需要存在,只能得到最新的105个。你已经拥有了所有105个候选人,你只需要聚合:

select distinct max(e105.id)
from events e105
join
(
  -- all 110 that are directly followed by  a110
  select just_before.id, just_before.category
  from
  (
    -- all 110 and their direct predecessor
    select events.id, min(before.id) as just_before_id
    from events
    left join events before on before.category = events.category and before.id < events.id
    where events.event = 110
    group by events.id
  ) event110
  join events just_before on just_before.id = event110.just_before_id and just_before.event = 110
) e110 on e110.category = e105.category and e110.id > e105.id
where events.event = 105
group by e110.id;