LIMIT和OFFSET
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LIMIT和OFFSET相关的知识,希望对你有一定的参考价值。
参考技术A LIMIT和OFFSET允许你只检索查询剩余部分产生的行的一部分:如果给出了一个限制计数,那么会返回数量不超过该限制的行(但可能更少些,因为查询本身可能生成的行数就比较少)。LIMIT ALL的效果和省略LIMIT子句一样,就像是LIMIT带有 NULL 参数一样。
OFFSET说明在开始返回行之前忽略多少行。OFFSET 0的效果和省略OFFSET子句是一样的,并且LIMIT NULL的效果和省略LIMIT子句一样,就像是OFFSET带有 NULL 参数一样。
如果OFFSET和LIMIT都出现了, 那么先忽略OFFSET行再返回LIMIT个行。
如果使用LIMIT,那么用一个ORDER BY子句把结果行约束成一个唯一的顺序是很重要的。否则你就会拿到一个不可预料的该查询的行的子集。你要的可能是第十到第二十行,但以什么顺序的第十到第二十?除非你指定了ORDER BY,否则顺序是不知道的。
查询优化器在生成查询计划时会考虑LIMIT,因此如果你给定LIMIT和OFFSET,那么你很可能收到不同的规划(产生不同的行顺序)。因此,使用不同的LIMIT/OFFSET值选择查询结果的不同子集将生成不一致的结果,除非你用ORDER BY强制一个可预测的顺序。这并非bug, 这是一个很自然的结果,因为 SQL 没有许诺把查询的结果按照任何特定的顺序发出,除非用了ORDER BY来约束顺序。
被OFFSET子句忽略的行仍然需要在服务器内部计算;因此,一个很大的OFFSET的效率可能还是不够高。
实施LIMIT和OFFSET时出现语法错误
通过执行PHP
上的SQL
,我跟随了MARIADB
为我提供数据。
function getData ($countsql, $datasql, $page, $limit, $input, $response){
try{
$offset = ($page-1) * $limit; //calculate what data you want
$db = new db();
$db = $db->connect();
$countQuery = $db->prepare( $countsql );
$dataQuery = $db->prepare( $datasql );
$dataQuery->bindParam(':limit', $limit, PDO::PARAM_INT);
$dataQuery->bindParam(':offset', $offset, PDO::PARAM_INT);
while(sizeof($input)){
$curr = array_pop($input);
$dataQuery->bindParam($curr["key"], $curr["keyvalue"]);
$countQuery->bindParam($curr["key"], $curr["keyvalue"]);
}
echo $datasql."+";
echo $limit."+";
echo $offset;
$dataQuery->execute();
$countQuery->execute();
$db = null; // clear db object
$count = $countQuery->fetch(PDO::FETCH_ASSOC);
$data = $dataQuery->fetchAll(PDO::FETCH_ASSOC);
if($count['COUNT']>0&&count($data)){
$data_arr=array();
$data_arr["records"]=array();
$data_arr["pagination"]=array();
$data_arr["records"] = $data;
$data_arr["pagination"] = array(
"count" => (int)$count['COUNT'],
"page" => $page,
"limit" => $limit,
"totalpages" => ceil($count['COUNT']/$limit)
);
return $response->withJson($data_arr,200);
}
else{
return $response->withJson (
array("msg" => "Nothing found."),
204
);
}
}catch( PDOException $e ) {
//return '{"error": {"msg":' . $e->getMessage() . '}';
return $response->withJson (
array("msg" => $e->getMessage()),
500
);
}
}
问题是当我在本地MARIADB
服务器上执行此操作时,代码工作正常,但是当我在联机服务器上执行此操作时,它会产生以下错误(请注意,我在最后打印了SQL + limit + offset调试)
{"msg":"SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''999999' OFFSET 0' at line 1"}SELECT * , (SELECT COUNT(*) FROM ART WHERE ART.AUTHOR_ID = AUTHOR.ID) as COUNT FROM AUTHOR LIMIT :limit OFFSET :offset+999999+0
语法或版本不匹配是否存在错误?
编辑
我也想问一件事,
这是获得COUNT个的正确方法
SELECT * , (SELECT COUNT(*) FROM ART WHERE ART.AUTHOR_ID = AUTHOR.ID) as COUNT FROM AUTHOR
或者我应该加入这两个表,然后计算相同的表吗?
答案
我不知道足够的PHP来回答您问题的第一部分,但这是我将使用的原始MySQL查询:
SELECT
AU.*,
COALESCE(AR.CNT, 0) AS COUNT
FROM AUTHOR AU
LEFT JOIN
(
SELECT AUTHOR_ID, COUNT(*) AS CNT
FROM ART
GROUP BY AUTHOR_ID
) AR
ON AU.ID = AR.AUTHOR_ID;
以上是关于LIMIT和OFFSET的主要内容,如果未能解决你的问题,请参考以下文章