一对多分页的SQL应该怎么写

网友投稿 332 2023-12-12

一对多分页的SQL应该怎么写

本篇文章为大家展示了一对多分页的SQL应该怎么写,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

一对多分页的SQL应该怎么写

前言

MySQL一对多的数据分页是非常常见的需求,比如我们要查询商品和商品的图片信息。但是很多人会在这里遇到分页的误区,得到不正确的结果。今天就来分析并解决这个问题。

2. 问题分析

我们先创建一个简单商品表和对应的商品图片关系表,它们之间是一对多的关系:

然后我分别写入了一些商品和这些商品对应的图片,通过下面的左连接查询可以看出它们之间具有明显的一对多关系:

SELECTP.PRODUCT_ID, P.PROD_NAME, PI.IMAGE_URLFROM PRODUCT_INFO P          LEFT JOIN PRODUCT_IMAGE PI                    ON P.PRODUCT_ID = PI.PRODUCT_ID

按照传统的思维我们的分页语句会这么写:

<resultMap id="ProductDTO" type="cn.felord.mybatis.entity.ProductDTO">     <id property="productId" column="product_id"/>     <result property="prodName" column="prod_name"/>     <collection property="imageUrls"  ofType="string">         <result column="image_url"/>     </collection> </resultMap>  <select id="page" resultMap="ProductDTO">SELECT P.PRODUCT_ID, P.PROD_NAME,PI.IMAGE_URL     FROM PRODUCT_INFO P              LEFT JOIN PRODUCT_IMAGE PI                        ON P.PRODUCT_ID = PI.PRODUCT_ID     LIMIT #{current},#{size}</select>

当我按照预想传入了(0,2)想拿到前两个产品的数据,结果并不是我期望的:

2020-06-21 23:35:54.515 DEBUG 10980 --- [main] c.f.m.mappers.ProductInfoMapper.page     : ==>  Preparing: SELECT P.PRODUCT_ID, P.PROD_NAME,PI.IMAGE_URL FROM PRODUCT_INFO P LEFT JOIN PRODUCT_IMAGE PI ON P.PRODUCT_ID = PI.PRODUCT_ID limit ?,?  2020-06-21 23:35:54.541 DEBUG 10980 --- [main] c.f.m.mappers.ProductInfoMapper.page     : ==> Parameters: 0(Long), 2(Long) 2020-06-21 23:35:54.565 DEBUG 10980 --- [main] c.f.m.mappers.ProductInfoMapper.page     : <==      Total: 2 page = [ProductDTO{productId=1, prodName=杯子, imageUrls=[http://asset.felord-/cup1.png, http://asset.felord-/cup2.png]}]

我期望的两条数据是杯子和笔记本,但是结果却只有一条。原来当一对多映射时结果集会按照多的一侧进行输出(期望4条数据,实际上会有7条),而前两条展示的只会是杯子的数据(如上图),合并后就只有一条结果了,这样分页就对不上了。那么如何才能达到我们期望的分页效果呢?

3. 正确的方式

正确的思路是应该先对主表进行分页,再关联从表进行查询。

抛开框架,我们的SQL应该先对产品表进行分页查询然后再左关联图片表进行查询:

SELECT P.PRODUCT_ID, P.PROD_NAME, PI.IMAGE_URL FROM (SELECT PRODUCT_ID, PROD_NAME       FROM PRODUCT_INFO       LIMIT #{current},#{size}) P          LEFT JOIN PRODUCT_IMAGE PI                    ON P.PRODUCT_ID = PI.PRODUCT_ID

这种写法的好处就是通用性强一些。但是MyBatis提供了一个相对优雅的路子,思路依然是开头所说的思路。只不过我们需要改造上面的Mybatis  XML配置

<resultMap id="ProductDTO" type="cn.felord.mybatis.entity.ProductDTO">     <id property="productId" column="product_id"/>     <result property="prodName" column="prod_name"/>      <!-- 利用 collection 标签提供的 select 特性 和 column   -->     <collection property="imageUrls" ofType="string" select="selectImagesByProductId" column="product_id"/> </resultMap> <!-- 先查询主表的分页数据    --> <select id="page" resultMap="ProductDTO">     SELECT PRODUCT_ID, PROD_NAME     FROM PRODUCT_INFO     LIMIT #{current},#{size} </select> <!--根据productId 查询对应的图片--> <select id="selectImagesByProductId" resultType="string">SELECT IMAGE_URL     FROM PRODUCT_IMAGE     WHERE PRODUCT_ID = #{productId}</select>

大部分情况下分页是很容易的,但是一对多还是有一些小小的陷阱的。一旦我们了解了其中的机制,也并不难解决。

上述内容就是一对多分页的SQL应该怎么写,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注行业资讯频道。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:MySQL常用基本操作都有哪些
下一篇:监控Oracle数据库的常用shell脚本怎么写
相关文章

 发表评论

暂时没有评论,来抢沙发吧~