mysql获取按多列排序的下一行

mysql获取按多列排序的下一行,mysql,sql,database,range,row,Mysql,Sql,Database,Range,Row,我有一个产品数据库。当我选择一个产品时,我想获得数据库中的下一个产品 例如: 我有ID为188的产品,我想得到下一个ID为167的产品 数据库: SELECT * FROM product ORDER BY title ASC, description ASC +----+----------------------+----------------------+ | id | title | description | +----+-------

我有一个产品数据库。当我选择一个产品时,我想获得数据库中的下一个产品

例如: 我有ID为188的产品,我想得到下一个ID为167的产品

数据库:

SELECT * FROM product ORDER BY title ASC, description ASC
+----+----------------------+----------------------+
| id | title                | description          |
+----+----------------------+----------------------+
|111 | Adjusterhouse        | Finetuning           |
+----+----------------------+----------------------+
|188 | Adjustment housing   | Height               |
+----+----------------------+----------------------+
|167 | Adjustment housing   | Oilpressure          |
+----+----------------------+----------------------+
|105 | Adjustment housing   | Suspension           |
+----+----------------------+----------------------+
|102 | Adjustment nut L+R.  | Packaging machinery  |
+----+----------------------+----------------------+
但是如果我使用下面的SQL语句,我得到的产品ID是102而不是167

SELECT * FROM product 
WHERE title > ? AND (title > ? OR description > ?) 
ORDER BY title ASC, description ASC LIMIT 1

有人能帮我处理这条SQL语句吗?

你用
对标题进行排序。假设您有记录188,标题是
调整壳
,如果您查看,您将设置第一条记录,标题是
调整壳
,实际上是记录102

将其更改为:

SELECT * FROM product 
 WHERE title >= ? AND description >= ? AND id != ? 
 ORDER BY title ASC, description ASC, id ASC LIMIT 1

在准备好的station参数绑定中将第二个
替换为id 188

您的方法是正确的。只需要一个小的更改,将第一个比较更改为“大于或等于”,而不仅仅是“大于”

只要
(title,description)
元组是唯一的,就可以正常工作。这是您想要的模式:

WHERE ( title >= ? )
  AND ( title > ? OR description > ? )
(唯一的变化是您需要一个“
标题”
=”比较作为
中的第一个条件,其中
。您拥有的其他一切都很好


如果
(标题、说明)
元组不能保证唯一…

我们需要在排序中添加额外的列。
id
列看起来是一个理想的候选者。这会变得有点复杂,但模式类似

WHERE ( title >= ? )
  AND ( title > ? OR 
                     (

                           ( description >= ? )
                       AND ( description > ? OR id > ? )

                     )
      )

 ORDER BY title ASC, description ASC, id ASC
请注意,我们嵌套了相同的模式;
description
id
使用的模式与
title
description
使用的模式相同


外部部分仍然是相同的模式,但是现在它在
标题上,而不是简单的
描述
,我们得到了在
(description,id)
元组上工作的条件。

您的用例没有很好的定义,但是实现这一点的一种方法是通过
限制
子句

因此,以下查询将返回第一行:

SELECT *
FROM product
ORDER BY title ASC, description ASC LIMIT 0, 1
将返回118,调整室,微调

然后,您可以使用:

SELECT *
FROM product
ORDER BY title ASC, description ASC LIMIT 1, 1
返回111,调整壳体,高度

您需要使用
选择(COUNT(1)-1)作为产品的最大偏移量
来了解数据“偏移”的距离。最大偏移量始终是行数减去1。在示例数据中,最大偏移量为:

SELECT *
FROM product
ORDER BY title ASC, description ASC LIMIT 4, 1

希望有帮助!

这种方法(使用偏移量)当你进入数千行的偏移量时,使用大型集合可能会非常昂贵。OP方法可能更有效,可以快速跳过不需要的行。对。正如我所说,用例没有很好的定义。我显然没有足够的技能来完整地回答这个问题。但是,现在在做什么是的,这是一个好问题。我假设为占位符提供的值是为先前获取的(当前显示的)值行。除了大集合的性能问题外,这种方法不处理插入到当前行下方的行。如果在此期间插入标题较低的行,则上一次查询中的第4行可以是下一次查询中的第5行,从而使下一次提取返回同一行。删除标题较低的行可能会导致n行被“跳过”。同意。我再说一遍,以澄清用例没有得到很好的定义。我做了两个假设:1)此产品表没有频繁添加到中,2)此产品表不超过数千行。在返回row id=167后,后续执行将再次返回row id=188。然后id=167。然后id=188。该算法将在这两行上卡住。您是对的,如果我们不能保证
(标题、说明)的正确性,我们需要在订单中引入
id
元组不是唯一的。@spencer7593忘记在clause@spencer7593当然,如果有重复的描述,你会得到同样的问题。有可能有重复的标题和描述吗?+1。这是正确的方法。只要将第一个大于比较值的值改为大于或等于。只要
(标题、说明)
是唯一的,您就会很好。(我们在这里显然假设为占位符提供的值是上次获取(当前显示)的值)行。如果它不是唯一的,我们需要引入另一个列以使其唯一,看起来
id
将是一个理想的候选者。根据您的数据,这是不必要的。谢谢,我现在这样得到它:从产品中选择*,其中title>=?和(title>=?)或((description>=?)和(description>或id>?)按标题ASC、描述ASC、id、ASC限制1排序,我认为效果很好,谢谢。@rrayy:我觉得where子句很合适。(必须提供
标题
值两次,
说明
值两次,以及
id
值一次。相同的模式可以扩展为使用第四列。如果您想按“颜色”或“单价”或其他方式订购。包括主键值(我假设id是主键)因为最后一行确保排序是确定的,并且在
ORDER BY
中没有两行具有完全相同的值。