子查询存在 group by 时,mybatis 分页异常

使用mybatis plus 自带的分页时报错 

xml 中的sql :

SELECT
f.id,
CONCAT(f.name,'评价') name,
a.create_time,
'作者' create_user
FROM
( SELECT id, MAX( create_time ) create_time FROM a
<where>
    <if test="params.isAll == 'unall'">id like CONCAT('%',#{params.userId},'%')
    </if>
    </where>
    GROUP BY id ) a
        LEFT JOIN tabB f ON a.id = f.id
<where>
    <if test="params.name!=null and params.name!='' ">
        name like concat('%',#{params.name},'%')
    </if>
</where>
order by a.create_time desc   

 打印日志:

Cause: java.sql.SQLSyntaxErrorException: Unknown column 'class_name' in 'where clause'
### The error may exist in file [D:\xxx\target\classes\mapper\xx\xx.xml]
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: SELECT COUNT(*) FROM (SELECT id, MAX(create_time) create_time FROM a GROUP BY id) a WHERE name LIKE concat('%', ?, '%')
### Cause: java.sql.SQLSyntaxErrorException: Unknown column 'name' in 'where clause'
; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Unknown column 'name' in 'where clause'

我的 name 字段 在 表 tabB 中,mybatis plus 自带的 select count (*)  却只截取了部分sql。导致 name 加到了 子查询 结果集中。

解决方案: 在最外层 套一层 ,查询sql 成为一个 子查询结果集。

select * from (

        SELECT f.id, CONCAT(f.name,'评价') name, a.create_time, '作者' create_user FROM ( SELECT id, MAX( create_time ) create_time FROM a <where> <if test="params.isAll == 'unall'">id like CONCAT('%',#{params.userId},'%') </if> </where> GROUP BY id ) a LEFT JOIN tabB f ON a.id = f.id <where> <if test="params.name!=null and params.name!='' "> name like concat('%',#{params.name},'%') </if> </where> order by a.create_time desc   

) tabA

猜测发生原因

        当sql 中 存在 () 时,mybatis plus 自带的分页 会直接使用 。导致发生sql 不完整问题。所以之后需要分页的sql。且这个sql存在子查询 或 ()时,要在最外层套一层 。防止发生问题!!!

### 解决 MyBatis 分页查询 GROUP BY 查询无结果报错 当使用 MyBatis 进行分页查询并涉及 `GROUP BY` ,可能会遇到查询不到数据报错的情况。这通常是因为 SQL 语句结构不当或分页插件处理方式引起的。 #### 原因分析 在某些情况下,MyBatis分页插件(如 PageHelper 或 MyBatis Plus)会对原始 SQL 语句进行修改,特别是对于带有子查询和聚合函数的复杂查询。如果这些修改影响到 `GROUP BY` 子句或其他关键部分,则可能导致查询失败[^1]。 #### 解决方案一:调整 SQL 语句 一种常见的做法是重构 SQL 语句以确保其逻辑清晰且易于被分页工具理解。具体来说: - 尽量简化主查询中的字段列表; - 如果可以的话,尝试将复杂的条件移至子查询内部而不是外部; - 使用窗口函数来替代传统的 `GROUP BY` 聚合操作,在支持此特性的数据库版本上实现更灵活的数据检索[^3]。 ```sql WITH ranked_data AS ( SELECT t.*, ROW_NUMBER() OVER (PARTITION BY column_to_group ORDER BY some_column) as rn FROM tabB t ) SELECT * FROM ranked_data WHERE rn = 1; ``` 上述代码通过创建一个 CTE 表达式 (`WITH`) 来计算每一组内的排名,并最终选取每组的第一条记录作为代表。这样既保留了原有功能又避免了一些潜在的问题。 #### 解决方案二:自定义分页逻辑 另一种方法是在应用程序层面手动控制分页行为而不依赖于现成的分页组件。这意味着开发者需要自己编写用于获取总数以及实际页面内容的方法。虽然这种方式增加了开发工作量但也提供了更大的灵活性[^4]。 例如,先执行一次统计总数量的查询: ```java int totalCount = sqlSession.selectOne("countQuery"); ``` 接着再做具体的分页查询: ```xml <select id="pagedData" resultType="com.example.Entity"> <!-- Your complex query here --> </select> ``` 最后根据前端传入的参数决定返回哪一部分的结果集给客户端显示。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值