本文目录一览:
- 1、php+mysql分页要求很简单!请大侠指教
- 2、php如果实现网站常用的翻页功能要用到mysql中的哪个句子?
- 3、php如何实现翻页显示
- 4、php+mysql文章分页
- 5、php的网站信息翻页功能跟mysql数据表哪些参数有关
- 6、PHP+MySQL高效的分页方法,如何优化LIMIT,OFFSET进行的分页?
php+mysql分页要求很简单!请大侠指教
首先你得把分页的原理弄懂,所谓分页显示,也就是将数据库中的结果集人为的分成一段一段的来显示,这里需要两个初始的参数:
每页多少条记录($PageSize),当前是第几页($page),现在只要再给我一个结果集,我就可以显示某段特定的结果出来。
至于其他的参数,比如:上一页($PreviousPageID)、下一页($NextPageID)、总页数($numPages)等等,都可以根据前边这几个东西得到。
以mysql数据库为例,如果要从表内截取某段内容,sql语句可以用:select * from table limit offset, rows。看看下面一组sql语句,尝试一下发现其中的规率。
前10条记录:select * from table limit 0,10
第11至20条记录:select * from table limit 10,10
第21至30条记录:select * from table limit 20,10
……
这一组sql语句其实就是当$PageSize=10的时候取表内每一页数据的sql语句,我们可以总结出这样一个模板:
select * from table limit ($CurrentPageID - 1) * $PageSize, $PageSize
拿这个模板代入对应的值和上边那一组sql语句对照一下看看是不是那么回事。搞定了最重要的如何获取数据的问题以后,剩下的就仅仅是传递参数,构造合适的sql语句然后使用php从数据库内获取数据并显示了。以下我将用具体代码加以说明。都是我自己写的,可以运行的:
?php
$db=new mysqli('localhost','root','6202','goodsmm');
$sql="select count(*) as amount from news";
$result=$db-query($sql);
//获取总数据量
$row=$result-fetch_array();
$amount=$row['amount'];
//获取当前页数
if(isset($_GET['page']))
{
$page=intval($_GET['page']);
}
else
{
$page=1;}
//每页数量
$page_size=2;
//计算总共有多少页
if($amount$PageSize)
{
$page_count=1;}
if($amount%$page_size){//拿总数据除以每页的总数,如果有余数,那么总页数等于商+1
$page_count=(int)($amount/$page_size)+1;}
else{
$page_count=(int)($amount/$page_size);}
//翻页链接
$page_string='';
if ($page==1)
$page_string='第一页|a href=ceshi.php?page='.($page+1).'下一页/a|';
elseif(($page==$page_count)||($page_count==0))
$page_string='a href=ceshi.php?page='.($page-1).'上一页/a|a href=ceshi.php?page='.$page_count.'尾页/a';
elseif(($page1)($page$page_count))
$page_string='a href=ceshi.php?page='.($page-1).'上一页/a|a href=ceshi.php?page='.($page+1).'下一页/a|';
//获取数据
$a=($page-1)*$page_size;
$b=$page_size;
$query_s="select * from news order by news_id limit $a,$b";
$result_s=$db-query($query_s);
$result_s_array=array();
while($rows=$result_s-fetch_array()){
array_push($result_s_array,$rows);
}
for($i=0;$i10;$i++){
echo $result_s_array[$i][2];
}
echo '一共有'.$page_count.'页p';
echo '当前为第'.$page.'页p';
echo $page_string;
?
php如果实现网站常用的翻页功能要用到mysql中的哪个句子?
重点是用到limit 起始下标值,每页数量,如:
select * from 表名 where 条件 order by 排序 limit 0,20;
php如何实现翻页显示
?
//设置当前页显示的数量(这个数量可任意设置)
$limit=20;
//初始化数据库搜索起始记录
if (!empty($start)) $start=0;
mysql_connect("localhost","","");
mysql_select_db(database);
//设置数据库记录总数
$result=mysql_query("select * from table");
$num_max=mysql_numrows($result);
$result=mysql_query("select * from table order by id desc limit $start,$limit);
$num=mysql_numrows($result);
echo "tabletrtd翻页功能/td/tr";
if (!empty($num)) {
for ($i=0;$i$num;$i++) {
$val=mysql_result($result,$i,"val");
$val1=mysql_result($result,$i,"val1");
echo "trtd$val/tdtd$val1/td/tr";
}
}
echo "trtd";
//设置向前翻页的跳转
$prve=$start-$limit;
if ($prve=0) {
echo "a href=page.php?start=$prveprve/a";
}
//设置向后翻页的跳转
$next=$start+$limit;
if ($next$num_max) {
echo "a href=page.php?start=$nextnext/a";
}
echo "/td/tr/table";
?
php+mysql文章分页
$page = $_GET['page'];这句你忘了写
------------
当然你还得用 is_numeric 函数判断一下,防注入.
php的网站信息翻页功能跟mysql数据表哪些参数有关
?php
$mysql_host = 'localhost';
$mysql_user = 'root';
$mysql_password = '';
$mysql_database = 'testdb';
///*Connect to the local server,可以在函数名前加上 @ 来抑制失败时产生的错误信息。
$link = mysql_connect($mysql_host,$mysql_user,$mysql_password) or die(mysql_error());
mysql_select_db($mysql_database) or die(mysql_error());
//set charset 设定字符集解决汉字问题
mysql_query("set names 'gbk'");
$rowsPerPage = 3; //定义每页的行数
$row = mysql_fetch_assoc(mysql_query("SELECT count(*) AS c FROM testmsg")); //查询表中的总记录数
$rows = $row['c']; //得到表中总记录数
$pages = ceil($rows / $rowsPerPage); //计算出页数
$curPage = 1; //当前要显示第几页,默认显示第1页
//$_REQUEST变量比较大,一般不用。常用的是$_POST,$_GET,二者与form表单method保持一致。$_GET还支持url传值
if(isset($_GET['curPage'])) //假如用户提交了指定的页数
$curPage = $_GET['curPage']; // 就将欲显示的页数设定为用户指定的值
//倒序查询
//echo $curPage;
$sql = "SELECT * FROM testmsg ORDER BY id DESC"." LIMIT ".($curPage -1)*$rowsPerPage.", $rowsPerPage"; //修改sql语句,使得可以查询出指定的结果集
//echo $sql;
$result = mysql_query($sql) or die(mysql_error());
//列表显示----------显示部分内容不变
while($row = mysql_fetch_assoc($result)){
echo "table width = '90%' align = 'center' cellpadding = '1' cellspacing = '1' bgcolor = 'blue' ";
echo " tr";
echo " td rowspan='2' width = '25%' bgcolor = 'white'";
echo " lispan style='color:red;'编号:/span{$row['id']}/li";
echo " lispan style='color:red;'用户:/span{$row['email']}/li";
echo " lispan style='color:red;'地址:/span{$row['ip']}/li";
echo " lispan style='color:red;'时间:/span{$row['time']}/li";
echo " lifont color = 'red'其他:/font{$row['other']}"; //html旧式写法
echo " /td";
echo " td bgcolor = 'yellow' font color = 'red'标题:/fonta href = modifyMsg.php?id={$row['id']}{$row['title']}/td";
echo " /tr";
echo " tr";
echo " td bgcolor = 'white' {$row['content']}/td";
echo " /tr";
echo "/table";
echo "br /";
}
//显示全部分页的链接
echo "div align = 'center'";
for($i=1;$i=$pages;$i++){ //循环显示,每个链接指定curPage属性为其指向的页数就可以了
echo "a href='testpage201.php?curPage=$i'$i/a ";
}
//下拉框分页
echo "form name = 'form1' action = 'testpage201.php?curPage=$curPage' method = 'GET'";
echo " select name= 'curPage' onchange = 'document.form1.submit();'";
for($i = 1; $i =$pages; $i++){
if($i == $curPage)
echo "option selected$i/option";
else
echo "option$i/option";
}
echo " /select";
echo " /form";
//首页、前页、后页、末页的链接
if($curPage1){
echo "a href = 'testpage201.php?curPage=1'首页/a ";
echo "a href = 'testpage201.php?curPage=".($curPage-1)."'前页/a ";
}
if($curPage$pages){
echo "a href='testpage201.php?curPage=".($curPage+1)."'后页/a ";
echo "a href = 'testpage201.php?curPage=$pages'末页/a ";
}
echo "/div";
//列表显示完毕
mysql_free_result($result);
mysql_close($link);
//$link-close()等同于mysql_close($link);
//$result-free()等同于mysql_free_result($result);
//$link-query($sql)等同于mysql_query($sql,$link);
/*
MySQL limit的实际用法的详细解析,在我们使用相关的查询语句的时候,一般都要返回前几条或是中间的某几行数据,这时你应如何处理呢?不必担心,MySQL数据库已经为我们提供了这样一个功能。
SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset
LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。MySQL LIMIT 接受一个或两个数字参数。参数必须是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目。初始记录行的偏移量是 0(而不是 1): 为了与 PostgreSQL 兼容,MySQL 也支持句法: LIMIT # OFFSET #。
MySQL SELECT * FROM table LIMIT 5,10;
检索记录行 6-15
为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1:
MySQL SELECT * FROM table LIMIT 95,-1;
检索记录行 96-last.
如果只给定一个参数,它表示返回最大的记录行数目:
MySQL SELECT * FROM table LIMIT 5;
检索前 5 个记录行。换句话说,LIMIT n 等价于 MySQL LIMIT 0,n。以上的相关内容就是对MySQL limit的用法详解的介绍,望你能有所收获。 */
?
?php
$link = mysql_connect("localhost","root","");
$sqlstr = "SELECT * FROM testmsg";
$send = mysql_db_query("testdb",$sqlstr);
$fdat = mysql_fetch_row($send);
$fdat = mysql_fetch_row($send); //试试调用两次的结果?
//mysql_fetch_row() 从和指定的结果标识关联的结果集中取得一行数据并作为数组返回。每个结果的列储存在一个数组的单元中,偏移量从 0 开始。
//依次调用 mysql_fetch_row() 将返回结果集中的下一行,如果没有更多行则返回 FALSE。
//print_r($fdat);
//foreach的两种写法
//foreach($fdat as $value){
foreach($fdat as $key = $value){
echo "$key:$valuebr /";
}
mysql_data_seek($send,0); //指针所在位置回到第一条记录上
$fdat = mysql_fetch_row($send);
foreach($fdat as $name = $valu){ //key = value 可以换写法命名
echo "$name:$valubr /";
}
mysql_free_result($send);
mysql_close($link);
/*
foreach
PHP 4 引入了 foreach 结构,和 Perl 以及其他语言很像。这只是一种遍历数组简便方法。foreach 仅能用于数组,当试图将其用于其它数据类型或者一个未初始化的变量时会产生错误。有两种语法,第二种比较次要但却是第一种的有用的扩展。
foreach (array_expression as $value)
statement
foreach (array_expression as $key = $value)
statement
第一种格式遍历给定的 array_expression 数组。每次循环中,当前单元的值被赋给 $value 并且数组内部的指针向前移一步(因此下一次循环中将会得到下一个单元)。
第二种格式做同样的事,只除了当前单元的键名也会在每次循环中被赋给变量 $key。
自PHP 5 起,还可能遍历对象。
Note:
当 foreach 开始执行时,数组内部的指针会自动指向第一个单元。这意味着不需要在 foreach 循环之前调用 reset()。
Note:
除非数组是被引用,foreach 所操作的是指定数组的一个拷贝,而不是该数组本身。foreach对数组指针有些副作用。除非对其重置,在 foreach 循环中或循环后都不要依赖数组指针的值。
自 PHP 5 起,可以很容易地通过在 $value 之前加上 来修改数组的元素。此方法将以引用赋值而不是拷贝一个值。
*/
?
?php
$link1 = mysql_connect("localhost","root","");
$link2 = mysql_connect("localhost","root","");;
//mysql_close();
//如果关闭连接,则无输出并报错。
/*
bool mysql_close ([ resource $link_identifier ] )
mysql_close() 关闭指定的连接标识所关联的到 MySQL 服务器的非持久连接。如果没有指定 link_identifier,则关闭上一个打开的连接。
*/
$result = mysql_query("select count(*) from testdb.testmsg"); //查询结果集
$row = mysql_fetch_row($result); //从结果集中取出一行作为枚举数组返回
print_r($row); //输出数据表的总行数的数组信息
echo $row[0];
?
PHP+MySQL高效的分页方法,如何优化LIMIT,OFFSET进行的分页?
很多应用往往只展示最新或最热门的几条记录,但为了旧记录仍然可访问,所以就需要个分页的导航栏。然而,如何通过MySQL更好的实现分页,始终是比较令人头疼的问题。虽然没有拿来就能用的解决办法,但了解数据库的底层或多或少有助于优化分页查询。
我们先从一个常用但性能很差的查询来看一看。
SELECT *
FROM city
ORDER BY id DESC
LIMIT 0, 15
这个查询耗时0.00sec。So,这个查询有什么问题呢?实际上,这个查询语句和参数都没有问题,因为它用到了下面表的主键,而且只读取15条记录。
CREATE TABLE city (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
city varchar(128) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;
真正的问题在于offset(分页偏移量)很大的时候,像下面这样:
SELECT *
FROM city
ORDER BY id DESC
LIMIT 100000, 15;
上面的查询在有2M行记录时需要0.22sec,通过EXPLAIN查看SQL的执行计划可以发现该SQL检索了100015行,但最后只需要15行。大的分页偏移量会增加使用的数据,MySQL会将大量最终不会使用的数据加载到内存中。就算我们假设大部分网站的用户只访问前几页数据,但少量的大的分页偏移量的请求也会对整个系统造成危害。Facebook意识到了这一点,但Facebook并没有为了每秒可以处理更多的请求而去优化数据库,而是将重心放在将请求响应时间的方差变小。
对于分页请求,还有一个信息也很重要,就是总共的记录数。我们可以通过下面的查询很容易的获取总的记录数。
SELECT COUNT(*)
FROM city;
然而,上面的SQL在采用InnoDB为存储引擎时需要耗费9.28sec。一个不正确的优化是采用 SQL_CALC_FOUND_ROWS,SQL_CALC_FOUND_ROWS 可以在能够在分页查询时事先准备好符合条件的记录数,随后只要执行一句 select FOUND_ROWS(); 就能获得总记录数。但是在大多数情况下,查询语句简短并不意味着性能的提高。不幸的是,这种分页查询方式在许多主流框架中都有用到,下面看看这个语句的查询性能。
SELECT SQL_CALC_FOUND_ROWS *
FROM city
ORDER BY id DESC
LIMIT 100000, 15;
这个语句耗时20.02sec,是上一个的两倍。事实证明使用 SQL_CALC_FOUND_ROWS 做分页是很糟糕的想法。
下面来看看到底如何优化。文章分为两部分,第一部分是如何获取记录的总数目,第二部分是获取真正的记录。
高效的计算行数
如果采用的引擎是MyISAM,可以直接执行COUNT(*)去获取行数即可。相似的,在堆表中也会将行数存储到表的元信息中。但如果引擎是InnoDB情况就会复杂一些,因为InnoDB不保存表的具体行数。
我们可以将行数缓存起来,然后可以通过一个守护进程定期更新或者用户的某些操作导致缓存失效时,执行下面的语句:
SELECT COUNT(*)
FROM city
USE INDEX(PRIMARY);
获取记录
下面进入这篇文章最重要的部分,获取分页要展示的记录。上面已经说过了,大的偏移量会影响性能,所以我们要重写查询语句。为了演示,我们创建一个新的表“news”,按照时事性排序(最新发布的在最前面),实现一个高性能的分页。为了简单,我们就假设最新发布的新闻的Id也是最大的。
CREATE TABLE news(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(128) NOT NULL
) ENGINE=InnoDB;
一个比较高效的方式是基于用户展示的最后一个新闻Id。查询下一页的语句如下,需要传入当前页面展示的最后一个Id。
SELECT *
FROM news WHERE id $last_id
ORDER BY id DESC
LIMIT $perpage
查询上一页的语句类似,只不过需要传入当前页的第一个Id,并且要逆序。
SELECT *
FROM news WHERE id $last_id
ORDER BY id ASC
LIMIT $perpage
上面的查询方式适合实现简易的分页,即不显示具体的页数导航,只显示“上一页”和“下一页”,例如博客中页脚显示“上一页”,“下一页”的按钮。但如果要实现真正的页面导航还是很难的,下面看看另一种方式。
SELECT id
FROM (
SELECT id, ((@cnt:= @cnt + 1) + $perpage - 1) % $perpage cnt
FROM news
JOIN (SELECT @cnt:= 0)T
WHERE id $last_id
ORDER BY id DESC
LIMIT $perpage * $buttons
)C
WHERE cnt = 0;
通过上面的语句可以为每一个分页的按钮计算出一个offset对应的id。这种方法还有一个好处。假设,网站上正在发布一片新的文章,那么所有文章的位置都会往后移一位,所以如果用户在发布文章时换页,那么他会看见一篇文章两次。如果固定了每个按钮的offset Id,这个问题就迎刃而解了。Mark Callaghan发表过一篇类似的博客,利用了组合索引和两个位置变量,但是基本思想是一致的。
如果表中的记录很少被删除、修改,还可以将记录对应的页码存储到表中,并在该列上创建合适的索引。采用这种方式,当新增一个记录的时候,需要执行下面的查询重新生成对应的页号。
SET p:= 0;
UPDATE news SET page=CEIL((p:= p + 1) / $perpage) ORDER BY id DESC;
当然,也可以新增一个专用于分页的表,可以用个后台程序来维护。
UPDATE pagination T
JOIN (
SELECT id, CEIL((p:= p + 1) / $perpage) page
FROM news
ORDER BY id
)C
ON C.id = T.id
SET T.page = C.page;
现在想获取任意一页的元素就很简单了:
SELECT *
FROM news A
JOIN pagination B ON A.id=B.ID
WHERE page=$offset;
还有另外一种与上种方法比较相似的方法来做分页,这种方式比较试用于数据集相对小,并且没有可用的索引的情况下—比如处理搜索结果时。在一个普通的服务器上执行下面的查询,当有2M条记录时,要耗费2sec左右。这种方式比较简单,创建一个用来存储所有Id的临时表即可(这也是最耗费性能的地方)。
CREATE TEMPORARY TABLE _tmp (KEY SORT(random))
SELECT id, FLOOR(RAND() * 0x8000000) random
FROM city;
ALTER TABLE _tmp ADD OFFSET INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, DROP INDEX SORT,ORDER BY random;
接下来就可以向下面一样执行分页查询了。
SELECT *
FROM _tmp
WHERE OFFSET = $offset
ORDER BY OFFSET
LIMIT $perpage;
简单来说,对于分页的优化就是。。。避免数据量大时扫描过多的记录。