MySQL根据前一行和下一行选择行

时间:2016-09-25 15:21:09

标签: mysql sql

假设我的表格如下:

          mytable
category |      begintime
---------|----------------------
cat1     | 2016-09-25 15:00:00
cat2     | 2016-09-25 16:00:00
cat1     | 2016-09-25 17:30:00
cat3     | 2016-09-25 19:00:00
cat1     | 2016-09-25 20:00:00
  :                 :

请注意,它没有ID号,begintime列是我的主键。

最后,我想选择所有被某个类别包围的行,即选择所有行,使前一行的类别为@catBefore,并选择下一行的类别是@catAfter

例如,我想要的是:

SELECT * FROM mytable WHERE previousRow.category = 'cat1' AND nextRow.category = 'cat1'

导致

    SELECT * FROM ...
category |      begintime
---------|----------------------
cat2     | 2016-09-25 16:00:00
cat3     | 2016-09-25 19:00:00
  :                 :

此中的previousRownextRow似乎无法定义。

我已经尝试了一些东西,但还没有成功。我的一个想法是首先选择上一个和下一个类别作为新列,如下所示:

SELECT mytable.*, 
       previousRow.category AS prevCat, 
       nextRow.category AS nextCat 
FROM mytable, [stuff-I-don't-know]

导致

     SELECT mytable.* ...
category |      begintime       | prevCat | nextCat
---------|----------------------|---------|---------
cat1     | 2016-09-25 15:00:00  | null    | cat2
cat2     | 2016-09-25 16:00:00  | cat1    | cat1
cat1     | 2016-09-25 17:30:00  | cat2    | cat3
cat3     | 2016-09-25 19:00:00  | cat1    | cat1
cat1     | 2016-09-25 20:00:00  | cat3    | ...
  :                 :

然后使用WHERE子句进行过滤。

这个想法是否可行,还是可以通过其他方式完成?

2 个答案:

答案 0 :(得分:1)

一种方法使用相关子查询。如果确实有主键声明,那么这在性能方面应该没问题:

<script>
function is_email(email)
{
    var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(email);
}

var selection = 'Integer lectus nisi, facilisis sit amet@blabla.test eleifend nec, pharetra ut augue.';
var before = new Array();
var email = "";
var after = new Array();

var email_found = false;
var selection_parts = selection.split(" ");
for (var i = 0 ; i < selection_parts.length ; i++)
{
  if (is_email(selection_parts[i]))
  {
    email = selection_parts[i]
    email_found = true;
  }
  else
  {
    if(email_found) after.push(selection_parts[i]);
    else before.push(selection_parts[i]);
  }
}
final_array = [before.join(" "), email, after.join(" ")]
console.log(final_array);
</script>

编辑:

您可以使用变量执行此操作:

select t.*
from (select t.*,
             (select t2.category
              from mytable t2
              where t2.begintime < t.begintime
              order by begintime desc
              limit 1
             ) as prev_category,        
             (select t2.category
              from mytable t2
              where t2.begintime > t.begintime
              order by begintime asc
              limit 1
             ) as next_category
  from mytable t
 ) t
where prev_category = @cat1 and next_category = @cat2;

答案 1 :(得分:1)

我做了这个...它似乎有效,但实际上似乎太慢了...... = \我会尝试改进它。请检查它是否适合您:

\1