1.情景展示
在實際開發過程中,分頁查詢是最常使用的,只要存在表格查詢,就會存在分頁查詢;
分頁的好處在於:減少查詢的數據量,不會給前端、后台服務器、數據庫造成壓力,減少用戶等待時間。
2.Oracle分頁
如果僅僅是SQL,不涉及前后端交互的話,最簡單的分頁查詢就是:
顯然,這種查詢,對於我們來說,基本上沒有意義,它往往蘊含着前后端交互:
由前端來決定要分頁大小PageSize,分頁的當前頁PageIndex;
后台根據PageIndex和PageSize計算出開始頁Start和結束頁End。
前端:傳當前頁數和每頁的大小
java:計算起始數和結束數
其核心點在於:
int start = (pageIndex - 1) * pageSize + 1;
int end = pageIndex * pageSize;
ibatis:
<select id="getACCESS_GRANT" parameterClass="map" resultClass="java.util.HashMap" >
<isNotNull property="END">
SELECT F.* FROM (
</isNotNull>
SELECT E.*,ROWNUM ROWNO FROM (
SELECT T.GRANTJK,T.SECRETKEY,T.ACCESSID,T.ID
FROM ACCESS_GRANT T
<include refid="ACCESS_GRANT_WHERE"/>
)E ORDER BY T.ID
<isNotNull property="END">
<![CDATA[ WHERE ROWNUM <= #END# ) F WHERE F.ROWNO >= #START#]]>
</isNotNull>
</select>
其核心點在於:
動態分頁,即:當參數start和end有值時,才進行分頁,沒值時,查詢的是所有數據。
3.Mysql分頁
最簡單查詢:
前端同上;
java:只需計算起始數;
其核心點在於:
計算起始數時,pageIndex需要-1,因為limit是從0開始的,不是1!
使用mysql我們只需要知道start(起始數)和pageSize(分頁大小)。
ibatis:
<select id="getMETA_THEME" parameterClass="map" resultClass="java.util.HashMap" cacheModel="cacheMETA_THEME">
<isNotNull property="START">
SELECT F.* FROM (
</isNotNull>
SELECT T.THEMEID,T.THEMENAME,T.THEMECODE,T.THEMELEVEL,T.PARENTTHEMEID,T.STATUS,T.ZJM,DATE_FORMAT(T.CREATETIME,'%Y-%m-%d') CREATETIME,T.REMARK1,T.REMARK2,T.REMARK3
FROM META_THEME T
<include refid="META_THEME_WHERE"/>
ORDER BY T.THEMEID
<isNotNull property="START">
) F
<![CDATA[ limit #START#,#PAGESIZE#]]>
</isNotNull>
</select>
其核心點在於:
動態分頁,即:當參數start有值時,才進行分頁,沒值時,查詢的是所有數據。
4.小結
Mysql和Oracle分頁的區別在於:
Mysql使用limit分頁,Oracle使用rownum分頁;
Mysql的limit 1,2 相當於:1<rownum≤3,得到的是第二行和第三行記錄;要想獲得前兩行的記錄,需要:
limit 0,2 相當於:0<rownum≤2
Oracle分頁是:1≤rownum≤2,得到的是第一行和第二行的記錄,也就是前兩行數據。
所以,這才是造成Mysql起始數從0開始,Oracle從1開始的真正原因。
其實Oracle也可以用int start = (pageIndex - 1) * pageSize;
不過,ibatis里面不能再用≥start,而是使用>start即可。
5.分頁+計數
我們知道,查詢數據往往涉及分頁,而分頁又要牽扯到總數;
所以,這里增加oracle和mysql的示例。
2022年2月13日12:02:22
oracle分頁+計數(ibatis)
分頁
<select id="getBASE_DICTIONARY_INFO" parameterClass="map"
resultClass="java.util.HashMap" cacheModel="cacheBASE_DICTIONARY_INFO">
<isNotNull prepend="" property="end">
SELECT F.* FROM (
</isNotNull>
SELECT E.*,ROWNUM ROWNO FROM (
SELECT A.DICTID,A.CLASSID,A.CODE,A.NAME,A.ZJM,
A.MEMO,A.OID,A.STATUS,
(SELECT CODE FROM BASE_DICTIONARY_KIND T WHERE A.CLASSID = T.CLASSID) CLASSCODE
FROM BASE_DICTIONARY_INFO A
<include refid="BASE_DICTIONARY_INFO_WHERE" />
ORDER BY A.OID
) E
<isNotNull prepend="" property="end">
<![CDATA[ WHERE rownum<=#end#) F where ROWNO>=#start# ]]>
</isNotNull>
</select>
計數
<select id="getBASE_DICTIONARY_INFO_COUNT" parameterClass="map"
resultClass="java.lang.Integer" cacheModel="cacheBASE_DICTIONARY_INFO">
SELECT COUNT(1)
FROM BASE_DICTIONARY_INFO A
<include refid="BASE_DICTIONARY_INFO_WHERE" />
</select>
動態where條件
<!--表(BASE_DICTIONARY_INFO)通用查詢條件-->
<sql id="BASE_DICTIONARY_INFO_WHERE">
<dynamic prepend="WHERE">
<isNotEmpty prepend="and" property="DICTID">
A.DICTID=#DICTID#
</isNotEmpty>
<isNotEmpty prepend="and" property="CLASSID">
A.CLASSID=#CLASSID#
</isNotEmpty>
</dynamic>
</sql>
mysql分頁+計數(mybatis)
分頁
<select id="getPersonInfoByIntoAddressList" resultType="map">
<![CDATA[
SELECT
( SELECT T2.PASS FROM SC_PASS_INFO T2 WHERE T2.ID = T.INTO_ADDRESS ) kaKou,
COUNT( 1 ) jiShu
FROM
SC_PERSON_INFO T
WHERE
T.CREATETIME >= STR_TO_DATE( #{startDate}, '%Y-%m-%d' )
AND T.CREATETIME < STR_TO_DATE( #{endDate}, '%Y-%m-%d' ) + 1
AND T.INTO_ADDRESS IS NOT NULL
AND T.INTO_ADDRESS != ''
GROUP BY
T.INTO_ADDRESS
ORDER BY
T.INTO_ADDRESS
LIMIT #{start},#{pageSize}
]]>
</select>
計數
<select id="getPersonInfoByIntoAddressTotal" resultType="long">
<![CDATA[
SELECT
COUNT( 1 ) totalCount
FROM
(
SELECT
1
FROM
SC_PERSON_INFO T
WHERE
T.CREATETIME >= STR_TO_DATE( #{startDate}, '%Y-%m-%d' )
AND T.CREATETIME < STR_TO_DATE( #{endDate}, '%Y-%m-%d' ) + 1
AND T.INTO_ADDRESS IS NOT NULL
AND T.INTO_ADDRESS != ''
GROUP BY
T.INTO_ADDRESS) b
]]>
</select>
6.list分頁
使用list進行手動分頁,見文末《mysql 存儲過程 示例》。
寫在最后
哪位大佬如若發現文章存在紕漏之處或需要補充更多內容,歡迎留言!!!