Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL根据上一行和下一行选择行_Mysql_Sql - Fatal编程技术网

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

MySQL根据上一行和下一行选择行,mysql,sql,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 :

假设我有一张像这样的桌子:

          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 mytable.*, 
       previousRow.category AS prevCat, 
       nextRow.category AS nextCat 
FROM mytable, [stuff-I-don't-know]
导致

    SELECT * FROM ...
category |      begintime
---------|----------------------
cat2     | 2016-09-25 16:00:00
cat3     | 2016-09-25 19:00:00
  :                 :
     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    | ...
  :                 :
上一行和下一行似乎无法定义

意念

我试过一些东西,但还没有成功。我的一个想法是首先选择上一个类别和下一个类别作为新列,因此类似于:

SELECT * FROM mytable WHERE previousRow.category = 'cat1' AND nextRow.category = 'cat1'
SELECT mytable.*, 
       previousRow.category AS prevCat, 
       nextRow.category AS nextCat 
FROM mytable, [stuff-I-don't-know]
导致

    SELECT * FROM ...
category |      begintime
---------|----------------------
cat2     | 2016-09-25 16:00:00
cat3     | 2016-09-25 19:00:00
  :                 :
     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子句进行过滤


这个想法是可能的,还是可以通过其他方式实现?

一种方法使用相关子查询。如果您确实有主键声明,这在性能方面应该还可以:

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;

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

SELECT 
  t1.category,
  t1.begintime
FROM myTable t1 -- current
INNER JOIN myTable t2 ON 1=1 -- prev
  AND t2.begintime < t1.begintime
INNER JOIN myTable t3 ON 1=1 -- next
  AND t3.begintime > t1.begintime
LEFT JOIN myTable t4 ON 1=1 -- between current and prev
  AND t4.begintime < t1.begintime
  AND t4.begintime > t2.begintime
LEFT JOIN myTable t5 ON 1=1 -- between current and next
  AND t5.begintime > t1.begintime
  AND t5.begintime < t3.begintime
WHERE 1=1
  AND t2.category = 'cat1' -- prev cat
  AND t3.category = 'cat1' -- next cat
  AND t4.begintime IS NULL -- nothing between current and prev
  AND t5.begintime IS NULL -- nothing between current and next
;

在子查询中添加限制1,否则将抛出错误子查询返回多个rowI,我也将对此进行注释。然而,它的执行速度不是很快,但这可能是因为我的桌子相当大。它已经运行了几分钟,但没有返回任何内容。我可以很容易地将它限制在前1000行左右,看看它是否真的有效吗?@konewka。是的,您可以向外部查询添加限制以查看其工作方式。你真的有开始时间的索引吗?@Abhishekginai。谢谢。欢迎戈登:你想查询整个表来进行上一个和下一个分类和筛选吗?假设你的前四行来自cat1。。。如果您正在查找prev和next等于cat1,则应仅返回第二条记录,或者也应返回第三条记录?@FelyppOliveira如果是这样,则第二条和第三条记录的前面和后面都有“cat1”,因此应返回。很遗憾,Edit没有返回任何信息。它执行了,但没有结果我尝试了它,并针对您的样本数据,得到了预期的结果。您将运行哪个上一个和下一个类别?如果您的数据在上一个和下一个之间没有任何类别,则预期结果是一个空集。。。查询可能运行良好。。。我认为您的筛选器/数据不应与任何内容匹配。。。你能提取其他样本数据吗?啊,是的,我明白了,它现在也在我的表上工作,一定是复制时出错了。然而,在1000个条目表上计算查询大约需要7秒,而Gordon Linoff的查询需要约0.11秒。我也试过在我原来的16000个条目表上运行它,但它已经运行了5分钟,没有结果,你认为查询可以改进吗?我说过它很慢。。。我认为这是可以改进的,但我现在做不到。。。请随意接受任何其他答案。。。如果我提高了性能,我将稍后编辑我的帖子。