使用含GROUP_CONCAT的查询分组后筛选同组最低价数据行
解决分组后保留最低价格记录的问题
我来帮你搞定这个问题!你的核心需求是在每组「除价格外其他数据完全一致」的记录里只保留价格最低的那条,然后再按brochure分组生成itemx字段对吧?下面给你两种可行的修改方案,根据你的MySQL版本选择即可:
方案一:使用窗口函数(MySQL 8.0+ 推荐)
窗口函数是处理这类分组取最值场景最简洁的方式,我们用ROW_NUMBER()给每个「非价格字段相同」的组排序,只保留价格最低的那条记录:
$results = $wpdb->get_results($wpdb->prepare(" SELECT t.brochure, GROUP_CONCAT(t.date, ':', SUBSTRING_INDEX(t.flights, '|', 2), ':', t.price, ':', t.board, ':', t.id SEPARATOR ',') AS itemx FROM ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY brochure, date, SUBSTRING_INDEX(flights, '|', 2), board, post_type ORDER BY price ASC ) AS rn FROM $tablename WHERE post_type = 'product' ) AS t WHERE t.rn = 1 GROUP BY t.brochure LIMIT 20 "));
逻辑说明:
- 子查询里的
PARTITION BY后面列出的就是你所说的「其他数据」字段,这些字段完全相同的记录会被分到同一个分组里 ORDER BY price ASC让每个分组里价格最低的记录行号rn为1- 主查询筛选
rn=1的记录,只保留每组最低价条目,再按brochure分组生成itemx
方案二:兼容MySQL 5.x版本(关联子查询)
如果你的服务器还在用MySQL 5.x,不支持窗口函数,可以用关联子查询先找出每个分组的最低价格,再匹配回原表:
$results = $wpdb->get_results($wpdb->prepare(" SELECT GROUP_CONCAT(t1.date, ':', SUBSTRING_INDEX(t1.flights, '|', 2), ':', t1.price, ':', t1.board, ':', t1.id SEPARATOR ',') AS itemx FROM $tablename t1 INNER JOIN ( SELECT brochure, date, SUBSTRING_INDEX(flights, '|', 2), board, post_type, MIN(price) AS min_price FROM $tablename WHERE post_type = 'product' GROUP BY brochure, date, SUBSTRING_INDEX(flights, '|', 2), board, post_type ) t2 ON t1.brochure = t2.brochure AND t1.date = t2.date AND SUBSTRING_INDEX(t1.flights, '|', 2) = SUBSTRING_INDEX(t2.flights, '|', 2) AND t1.board = t2.board AND t1.post_type = t2.post_type AND t1.price = t2.min_price WHERE t1.post_type = 'product' GROUP BY t1.brochure LIMIT 20 "));
逻辑说明:
- 子查询
t2先计算每个「非价格字段相同」分组的最低价格min_price - 主查询通过
INNER JOIN把原表t1和t2关联,只保留价格等于对应分组最低价格的记录 - 最后按
brochure分组生成itemx
注意:如果同一个分组里有多个记录价格相同且都是最低价,方案二会保留所有这些记录。如果只需要其中一条,可以在子查询里额外加上
MIN(id)来匹配唯一的记录。
内容的提问来源于stack exchange,提问作者Bobby WW
相关产品推荐
相关产品推荐

