我不得不解决类似的问题,但考虑到我们总能得到相同的行数的情况下,需要的话,即使该行已接近顶部或底部结果集(即,不完全在中间)。
该解决方案是由OMG小马响应的调整,但在ROWNUM在该行马克塞斯:
set @id = 7;
SELECT natSorted.id
FROM (
SELECT gravitySorted.* FROM (
SELECT Media.id, IF(id <= @id, @gravity := @gravity + 1, @gravity := @gravity - 1) AS gravity
FROM Media, (SELECT @gravity := 0) g
) AS gravitySorted ORDER BY gravity DESC LIMIT 10
) natSorted ORDER BY id;
这里有一个休息的发生了什么事下来:
注:下面的例子中,我做了一个20行的表格,并删除了id 6和9,以确保id中的间隔不会影响结果
首先,我们将每行分配一行以你正在寻找的特定行为中心的重力值(在这种情况下,id是7)。越接近排是为所需的行,较高的值将是:
SET @id = 7;
SELECT Media.id, IF(id <= @id, @gravity := @gravity + 1, @gravity := @gravity - 1) AS gravity
FROM Media, (SELECT @gravity := 0) g
回报:
+----+---------+
| id | gravity |
+----+---------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 7 | 6 |
| 8 | 5 |
| 10 | 4 |
| 11 | 3 |
| 12 | 2 |
| 13 | 1 |
| 14 | 0 |
| 15 | -1 |
| 16 | -2 |
| 17 | -3 |
| 18 | -4 |
| 19 | -5 |
| 20 | -6 |
| 21 | -7 |
+----+---------+
接下来,我们为了通过重力值和极限上的所需数量的所有结果行:
SET @id = 7;
SELECT gravitySorted.* FROM (
SELECT Media.id, IF(id <= @id, @gravity := @gravity + 1, @gravity := @gravity - 1) AS gravity
FROM Media, (SELECT @gravity := 0) g
) AS gravitySorted ORDER BY gravity DESC LIMIT 10
回报:
+----+---------+
| id | gravity |
+----+---------+
| 7 | 6 |
| 5 | 5 |
| 8 | 5 |
| 4 | 4 |
| 10 | 4 |
| 3 | 3 |
| 11 | 3 |
| 2 | 2 |
| 12 | 2 |
| 1 | 1 |
+----+---------+
在这一点上,我们有所有需要的ID,我们只需要他们回来排序到原来的顺序:
set @id = 7;
SELECT natSorted.id
FROM (
SELECT gravitySorted.* FROM (
SELECT Media.id, IF(id <= @id, @gravity := @gravity + 1, @gravity := @gravity - 1) AS gravity
FROM Media, (SELECT @gravity := 0) g
) AS gravitySorted ORDER BY gravity DESC LIMIT 10
) natSorted ORDER BY id;
回报:
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 7 |
| 8 |
| 10 |
| 11 |
| 12 |
+----+
是否有差距这将无法正常工作ID的。 – Will 2009-11-28 21:41:31
噢,很好的电话,对不起。 – malonso 2009-11-29 14:57:02