【问题标题】:How to select previous or next row ordered by multiple text columns如何选择按多个文本列排序的上一行或下一行
【发布时间】:2011-09-21 10:22:03
【问题描述】:

我有一个表单来编辑 mysql 表列。我可以单击链接并加载上一个、下一个、第一行或最后一行。我可以订购列(最多订购四列)。所以当我按 Prev。或下一步,必须先对列进行排序,然后我才能得到结果。我为此使用mysql View。重要的是要知道列是文本,但 id 是数字。我通常先按文本列排序,然后按 id 排序。

这是我对单列顺序有用的查询。

上一个:

  SELECT  x.* 
    FROM  test_view x, test_view y 
   WHERE   y.`id` = 13 
           AND ( x.`cat` < y.`cat` OR ( x.`cat` = y.`cat` AND x.`id` < y.`id`)) 
ORDER BY  x.`cat`, x.`id` DESC   
   LIMIT  0,1

下一步:

  SELECT  x.* 
    FROM  test_view x, test_view y 
   WHERE  y.`id` = 13 
          AND (x.`cat` > y.`cat` OR (x.`cat` = y.`cat` AND x.`id` > y.`id`)) 
ORDER BY  x.`cat`, x.`id` ASC   
   LIMIT  0,1

我试图扩展它以找到多个列,如下所示:

SELECT x . *
FROM ukazka_view x, ukazka_view y
WHERE y.`id` =1
AND (
x.`cat` < y.`cat`
OR (
x.`cat` = y.`cat`
AND x.`id` < y.`id`
)
)
AND (
x.`typ` < y.`typ`
OR (
x.`typ` = y.`typ`
AND x.`id` < y.`id`
)
)
AND (
x.`diff` < y.`diff`
OR (
x.`diff` = y.`diff`
AND x.`id` < y.`id`
)
)
ORDER BY x.`cat` DESC , x.`typ` DESC , x.`diff` DESC , x.`id` DESC
LIMIT 0 , 1

但这没有结果。

已编辑:

我尝试为实际行 ID 为 1 的情况编写查询。

    SELECT x.* FROM  ukazka_view x INNER JOIN ukazka_view y ON  
( x.`cat` < y.`cat` OR 
( x.`cat` = y.`cat` AND x.`id` < y.`id`) OR
( x.`cat` = y.`cat` AND y.`id` = 1 AND x.`id` > y.`id`))

与 ( x.typ typ 或 ( x.typ = y.typ AND x.id id) 或 ( x.typ = y.typ AND y.id = 1 AND x.id > y.id)) 和 ( x.diff diff 或 ( x.diff = y.diff AND x.id id) 或 ( x.diff = y.diff AND y.id = 1 AND x.id > y.id)) 在哪里 y.id = 1 ORDER BY x.cat DESC, x.typ DESC, x.diff DESC, x.id DESC LIMIT 0,1

这会查找上一行。行为有点奇怪,但有效。所以当我去最后一个值时,我得到了 id=1。然后当我按上一个(此查询)时,它会到达 id=82,当我再次按上一个 id=81 时,依此类推,直到我得到 id=2。只有当我按下/选择 Last 时,我才能到达 id=1。

【问题讨论】:

  • 隐式连接是一种反模式。我建议您改用显式联接,并摆脱 1989 年。
  • 前两个代码是由比我更了解 sql 的人提供给我的。我只是新手,所以我不明白你的评论。此外,前两个代码取自一个在我国享有盛誉的网站的示例。
  • 隐式连接的问题在于它们混合了过滤器和连接条件。这是不好且令人困惑的,因此显式连接语法,请参见下面的答案。发明于 1992 年(!)。此处分别列出了连接条件。这使得查询更清晰,更容易调试。否则它的工作原理相同。

标签: mysql select sql-order-by


【解决方案1】:
SELECT x.*
FROM ukazka_view x
INNER JOIN ukazka_view y 
  ON  (x.cat  < y.cat  OR (x.cat  = y.cat  AND x.id < y.id)) 
  AND (x.typ  < y.typ  OR (x.typ  = y.typ  AND x.id < y.id))  
  AND (x.diff < y.diff OR (x.diff = y.diff AND x.id < y.id))
WHERE y.id = 1
ORDER BY x.cat DESC , x.typ DESC , x.diff DESC , x.id DESC
LIMIT 1 OFFSET 0

我在这个查询中看到的问题是 id 不能小于 1。
所以x.id &lt; y.id 永远是假的。
只剩下

....
  ON  (x.cat  < y.cat)
  AND (x.typ  < y.typ)
  AND (x.diff < y.diff)

作为连接标准。

【讨论】:

  • (x.cat &lt; y.cat OR (x.cat = y.cat AND x.id &lt; y.id)) 在 MySQL 中可以更简洁地写成:(x.cat, x.id) &lt; (y.cat, y.id)
  • @ypercube,哇,你从哪里弄来的宝石?我很想有一个记录这种行为的链接。
  • @Johan:“我在这个查询中看到的问题是 id 不能小于 1。” - 你的意思是有问题的前两个代码不应该工作吗?我现在测试了你的代码,它似乎运行良好。在这一刻,我正在尝试修复我的代码以与 First 和 Last 一起使用。感谢这段代码。
  • @Joe,x.id &lt; y.id 永远不会与 where y.id = 1 结合使用,如果 y.id 可以 > 1,那么它可能会起作用。
  • @Johan:我不记得链接了,如果我找到了,我会写在这里。我在这里尝试解决(字典)问题时最后在这里找到它,以一些非常复杂的代码结束,只是为了找出简单的(a,b,c) &lt; (x,y,z) 而不是我的 6 个线段 :)
猜你喜欢
  • 2011-07-01
  • 2016-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多