fix(药分享): 商品清单去重改用代表行,修复 ONLY_FULL_GROUP_BY 报错
现象:小程序“药分享”页 onShow 抛 TypeError: Cannot read properties of undefined (reading 'list') 根因在本接口:/yxe/yxe-share-detail/page?groupByProduct=true 返回 code=1 且不带 data,前端取 data.list 直接抛异常,中断整个 onShow。 原因:原 SQL 为 `SELECT a.* FROM yxe_share_detail a WHERE ... GROUP BY a.goods_name`。 MySQL 开启 ONLY_FULL_GROUP_BY 时,SELECT 列表中 a.* 的非分组列既不在 GROUP BY 内也不函数依赖于分组列,直接报 Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column '...a.id' which is not functionally dependent on columns in GROUP BY clause 生产库恰好关闭了该 sql_mode 才长期未暴露,本地库(MySQL 9.7)已开启。 改法:取每个 goods_name 在**筛选结果集内**的最小 id 作为代表行, 语义与原 WHERE 之后 GROUP BY 一致。内层子查询重复同一套筛选条件, 否则按 province/city 过筛后该代表行可能不在结果集中,对应商品会整个消失。 未用窗口函数,不依赖 MySQL 8.0。 验证(本地库): - groupByProduct=true code=0,5 个去重商品(修复前 code=1) - groupByProduct + city count=3,内外层条件一致生效 - groupByProduct + goodsName count=2 - 不带 groupByProduct count=12,原有行为不变
This commit is contained in:
@@ -2,7 +2,28 @@
|
|||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="com.gxwebsoft.yxe.mapper.YxeShareDetailMapper">
|
<mapper namespace="com.gxwebsoft.yxe.mapper.YxeShareDetailMapper">
|
||||||
|
|
||||||
<!-- 关联查询sql -->
|
<!--
|
||||||
|
关联查询sql
|
||||||
|
|
||||||
|
【按商品去重(groupByProduct)为什么不能用 GROUP BY】
|
||||||
|
原先写成 `SELECT a.* FROM yxe_share_detail a WHERE ... GROUP BY a.goods_name`。
|
||||||
|
MySQL 开启 ONLY_FULL_GROUP_BY 时,SELECT 列表 a.* 中的非分组列既不在
|
||||||
|
GROUP BY 中、也不函数依赖于分组列,会直接抛:
|
||||||
|
Expression #1 of SELECT list is not in GROUP BY clause and contains
|
||||||
|
nonaggregated column '...a.id' which is not functionally dependent on
|
||||||
|
columns in GROUP BY clause
|
||||||
|
接口因此返回 code=1 且**不带 data**,前端 getProductList 里 `data.list`
|
||||||
|
就抛 "Cannot read properties of undefined (reading 'list')",
|
||||||
|
整个 onShow 中断,页面数据全部不渲染。
|
||||||
|
|
||||||
|
【现在的写法】
|
||||||
|
取每个 goods_name 在**筛选结果集内**的最小 id 作为代表行,语义与原先的
|
||||||
|
WHERE 之后 GROUP BY 完全一致(代表行只能从筛选后的行里产生)。
|
||||||
|
内层子查询必须重复同一套筛选条件:若只按整表取 MIN(id),当 province/city
|
||||||
|
过筛后该代表行可能不在结果集中,对应商品会整个消失。
|
||||||
|
|
||||||
|
用 MIN(id) + IN 而非窗口函数,是因为不依赖 MySQL 8.0。
|
||||||
|
-->
|
||||||
<sql id="selectSql">
|
<sql id="selectSql">
|
||||||
SELECT a.*
|
SELECT a.*
|
||||||
FROM yxe_share_detail a
|
FROM yxe_share_detail a
|
||||||
@@ -50,10 +71,58 @@
|
|||||||
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
)
|
)
|
||||||
</if>
|
</if>
|
||||||
</where>
|
|
||||||
<if test="param.groupByProduct != null">
|
<if test="param.groupByProduct != null">
|
||||||
GROUP BY a.goods_name
|
AND a.id IN (
|
||||||
|
SELECT MIN(b.id)
|
||||||
|
FROM yxe_share_detail b
|
||||||
|
WHERE 1 = 1
|
||||||
|
<if test="param.id != null">
|
||||||
|
AND b.id = #{param.id}
|
||||||
</if>
|
</if>
|
||||||
|
<if test="param.shareId != null">
|
||||||
|
AND b.share_id = #{param.shareId}
|
||||||
|
</if>
|
||||||
|
<if test="param.province != null">
|
||||||
|
AND b.province = #{param.province}
|
||||||
|
</if>
|
||||||
|
<if test="param.city != null">
|
||||||
|
AND b.city = #{param.city}
|
||||||
|
</if>
|
||||||
|
<if test="param.goodsName != null">
|
||||||
|
AND b.goods_name LIKE CONCAT('%', #{param.goodsName}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.spec != null">
|
||||||
|
AND b.spec LIKE CONCAT('%', #{param.spec}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.num != null">
|
||||||
|
AND b.num = #{param.num}
|
||||||
|
</if>
|
||||||
|
<if test="param.sortNumber != null">
|
||||||
|
AND b.sort_number = #{param.sortNumber}
|
||||||
|
</if>
|
||||||
|
<if test="param.status != null">
|
||||||
|
AND b.status = #{param.status}
|
||||||
|
</if>
|
||||||
|
<if test="param.deleted != null">
|
||||||
|
AND b.deleted = #{param.deleted}
|
||||||
|
</if>
|
||||||
|
<if test="param.deleted == null">
|
||||||
|
AND b.deleted = 0
|
||||||
|
</if>
|
||||||
|
<if test="param.createTimeStart != null">
|
||||||
|
AND b.create_time >= #{param.createTimeStart}
|
||||||
|
</if>
|
||||||
|
<if test="param.createTimeEnd != null">
|
||||||
|
AND b.create_time <= #{param.createTimeEnd}
|
||||||
|
</if>
|
||||||
|
<if test="param.keywords != null">
|
||||||
|
AND (b.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
)
|
||||||
|
</if>
|
||||||
|
GROUP BY b.goods_name
|
||||||
|
)
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<!-- 分页查询 -->
|
<!-- 分页查询 -->
|
||||||
|
|||||||
Reference in New Issue
Block a user