使用 order by 和 limit 的奇怪结果
Strange results using order by and limit
我正在尝试使用 SQL 设置分页。我想要每页 3 个结果,这是我所做的:
SELECT mot_cle.* FROM mot_cle
ORDER BY hits DESC LIMIT 3 OFFSET 0; --Page 1
SELECT mot_cle.* FROM mot_cle
ORDER BY hits DESC LIMIT 3 OFFSET 3; --Page 2
SELECT mot_cle.* FROM mot_cle
ORDER BY hits DESC LIMIT 3 OFFSET 6; --Page 3
SELECT mot_cle.*
FROM mot_cle
ORDER BY hits DESC LIMIT 3 OFFSET 9; --Page 4
我检查了很多次,这不是很复杂,但我的结果并不是我所期望的:
第 1 页:
+-----+--------+------+
| id | mot | hits |
+-----+--------+------+
| 2 | test | 46 |
| 1 | blabla | 5 |
| 475 | intro | 3 |
+-----+--------+------+
第 2 页:
+-----+-------+------+
| id | mot | hits |
+-----+-------+------+
| 478 | vrai | 1 |
| 26 | ouest | 1 |
| 27 | serie | 1 |
+-----+-------+------+
第 3 页:
+-----+-------+------+
| id | mot | hits |
+-----+-------+------+
| 27 | serie | 1 |
| 26 | ouest | 1 |
| 478 | vrai | 1 |
+-----+-------+------+
第 4 页:
+-----+-------+------+
| id | mot | hits |
+-----+-------+------+
| 27 | serie | 1 |
| 26 | ouest | 1 |
| 478 | vrai | 1 |
+-----+-------+------+
如您所见,第 2、3 和 4 页的结果相同...
当我将 4 页合二为一时:
SELECT mot_cle.* FROM mot_cle
ORDER BY hits DESC LIMIT 20 OFFSET 0;
结果:
+-----+-------------+------+
| id | mot | hits |
+-----+-------------+------+
| 2 | test | 46 |
| 1 | blabla | 5 |
| 475 | intro | 3 |
| 35 | acteurs | 1 |
| 36 | milieu | 1 |
| 37 | industriel | 1 |
| 38 | plaire | 1 |
| 39 | grandes | 1 |
| 40 | ingenieries | 1 |
| 41 | francaises | 1 |
| 34 | partenaire | 1 |
| 33 | rthgyjhkj | 1 |
| 32 | cool | 1 |
| 31 | super | 1 |
| 30 | vieux | 1 |
| 29 | moteur | 1 |
| 28 | yahoo | 1 |
| 27 | serie | 1 |
| 26 | ouest | 1 |
| 478 | vrai | 1 |
+-----+-------------+------+
可能是我遗漏了一些东西或者排序结果和使用limit/offset不兼容,我不知道出了什么问题。
而不是使用
Limit 3 offset 0
Limit 3 offset 3
Limit 3 offset 6
Limit 3 offset 9
你应该可以使用
Limit 0,3
Limit 3,3
Limit 6,3
Limit 9,3
效果相同
这里的问题是所有行的命中数都是 1
,因此它们在使用 ORDER BY hits
时的位置是不确定的。由于每次访问页面时都执行新查询,因此行将 "scrambled" 重新显示。
为了让您的页面保持一致,您也可以按他们的 id 排序:
SELECT mot_cle.* FROM mot_cle ORDER BY hits DESC, id ASC LIMIT 3 OFFSET 0; --Page 1
LIMIT
基本上 "aborts" 一旦找到足够的匹配行就进行查询。例如。如果您有 LIMIT 2
,那么只要找到与 join
/where
子句匹配的两行,查询的其余部分就会消失,您会得到这两行。
但是如果你有一个ORDER BY
,那么整个匹配的结果集都会被排序,然后 LIMIT 被应用到那个排序的结果集。
例如如果您有一些记录将作为 5,10,203,3,92
返回,则
SELECT id ... LIMIT 2 -> (5,10),203,3,92
^^^^^^---actual returned-to-client results
SELECT id ... ORDER BY id LIMIT 2 -> 3,5,10,92,203 -> (3,5),10,92,203
^^---internal-only results
^^^^--actual returned-to-client results.
我正在尝试使用 SQL 设置分页。我想要每页 3 个结果,这是我所做的:
SELECT mot_cle.* FROM mot_cle
ORDER BY hits DESC LIMIT 3 OFFSET 0; --Page 1
SELECT mot_cle.* FROM mot_cle
ORDER BY hits DESC LIMIT 3 OFFSET 3; --Page 2
SELECT mot_cle.* FROM mot_cle
ORDER BY hits DESC LIMIT 3 OFFSET 6; --Page 3
SELECT mot_cle.*
FROM mot_cle
ORDER BY hits DESC LIMIT 3 OFFSET 9; --Page 4
我检查了很多次,这不是很复杂,但我的结果并不是我所期望的:
第 1 页:
+-----+--------+------+
| id | mot | hits |
+-----+--------+------+
| 2 | test | 46 |
| 1 | blabla | 5 |
| 475 | intro | 3 |
+-----+--------+------+
第 2 页:
+-----+-------+------+
| id | mot | hits |
+-----+-------+------+
| 478 | vrai | 1 |
| 26 | ouest | 1 |
| 27 | serie | 1 |
+-----+-------+------+
第 3 页:
+-----+-------+------+
| id | mot | hits |
+-----+-------+------+
| 27 | serie | 1 |
| 26 | ouest | 1 |
| 478 | vrai | 1 |
+-----+-------+------+
第 4 页:
+-----+-------+------+
| id | mot | hits |
+-----+-------+------+
| 27 | serie | 1 |
| 26 | ouest | 1 |
| 478 | vrai | 1 |
+-----+-------+------+
如您所见,第 2、3 和 4 页的结果相同... 当我将 4 页合二为一时:
SELECT mot_cle.* FROM mot_cle
ORDER BY hits DESC LIMIT 20 OFFSET 0;
结果:
+-----+-------------+------+
| id | mot | hits |
+-----+-------------+------+
| 2 | test | 46 |
| 1 | blabla | 5 |
| 475 | intro | 3 |
| 35 | acteurs | 1 |
| 36 | milieu | 1 |
| 37 | industriel | 1 |
| 38 | plaire | 1 |
| 39 | grandes | 1 |
| 40 | ingenieries | 1 |
| 41 | francaises | 1 |
| 34 | partenaire | 1 |
| 33 | rthgyjhkj | 1 |
| 32 | cool | 1 |
| 31 | super | 1 |
| 30 | vieux | 1 |
| 29 | moteur | 1 |
| 28 | yahoo | 1 |
| 27 | serie | 1 |
| 26 | ouest | 1 |
| 478 | vrai | 1 |
+-----+-------------+------+
可能是我遗漏了一些东西或者排序结果和使用limit/offset不兼容,我不知道出了什么问题。
而不是使用
Limit 3 offset 0
Limit 3 offset 3
Limit 3 offset 6
Limit 3 offset 9
你应该可以使用
Limit 0,3
Limit 3,3
Limit 6,3
Limit 9,3
效果相同
这里的问题是所有行的命中数都是 1
,因此它们在使用 ORDER BY hits
时的位置是不确定的。由于每次访问页面时都执行新查询,因此行将 "scrambled" 重新显示。
为了让您的页面保持一致,您也可以按他们的 id 排序:
SELECT mot_cle.* FROM mot_cle ORDER BY hits DESC, id ASC LIMIT 3 OFFSET 0; --Page 1
LIMIT
基本上 "aborts" 一旦找到足够的匹配行就进行查询。例如。如果您有 LIMIT 2
,那么只要找到与 join
/where
子句匹配的两行,查询的其余部分就会消失,您会得到这两行。
但是如果你有一个ORDER BY
,那么整个匹配的结果集都会被排序,然后 LIMIT 被应用到那个排序的结果集。
例如如果您有一些记录将作为 5,10,203,3,92
返回,则
SELECT id ... LIMIT 2 -> (5,10),203,3,92
^^^^^^---actual returned-to-client results
SELECT id ... ORDER BY id LIMIT 2 -> 3,5,10,92,203 -> (3,5),10,92,203
^^---internal-only results
^^^^--actual returned-to-client results.