本文目錄一覽:
- 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;
簡單來說,對於分頁的優化就是。。。避免數據量大時掃描過多的記錄。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/258208.html