使用 Query Monitor 调试时,我发现 WordPress 生成的 SQL 查询如下,并且它有报错 ORDER BY 相关的问题:
SELECT wp_posts.ID
FROM wp_posts
LEFT JOIN wp_term_relationships
ON (wp_posts.ID = wp_term_relationships.object_id)
INNER JOIN wp_postmeta
ON ( wp_posts.ID = wp_postmeta.post_id )
WHERE 1=1
AND ( wp_term_relationships.term_taxonomy_id IN (1890041) )
AND ( wp_postmeta.meta_key = 'anyx-training-order' )
AND ((wp_posts.post_type = 'anyx-training'
AND (wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'complete'
OR wp_posts.post_status = 'private')))
GROUP BY wp_posts.ID
ORDER BY wp_postmeta.meta_value ASC;
报错信息如下:
ERROR 1055 (42000): Expression #1 of ORDER BY is not in GROUP BY clause and contains nonaggregated column '' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
这个错误信息 ERROR 1055 (42000): Expression #1 of ORDER BY is not in GROUP BY clause and contains nonaggregated column '' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by 是 MySQL 在启用 ONLY_FULL_GROUP_BY SQL 模式时抛出的,下面为你详细解释该错误的含义和产生原因,以及解决办法。
错误含义
在 MySQL 开启 ONLY_FULL_GROUP_BY 模式时,SELECT、HAVING 或者 ORDER BY 子句里所使用的列,必须满足以下两个条件之一,否则就会报错:
该列必须包含在 GROUP BY 子句中。
该列必须使用了聚合函数(例如 SUM()、COUNT()、AVG() 等)。
产生原因
你提供的 SQL 语句中,ORDER BY 子句使用了 wp_postmeta.meta_value 列,然而这个列既没有出现在 GROUP BY 子句中,也没有使用聚合函数进行处理。这就违背了 ONLY_FULL_GROUP_BY 模式的规则,因为 wp_postmeta 表中可能存在多条与 wp_posts.ID 关联的记录,每条记录的 meta_value 可能不同,所以 MySQL 无法明确按照哪个 meta_value 进行排序。
解决办法
1. 修改查询语句
使用聚合函数来处理 ORDER BY 子句中的列,确保其符合 ONLY_FULL_GROUP_BY 模式的要求。例如,使用 MIN() 或者 MAX() 函数来获取 meta_value 的最小值或者最大值:
收起
sql
SELECT wp_posts.ID, MIN(wp_postmeta.meta_value) AS min_meta_value
FROM wp_posts
LEFT JOIN wp_term_relationships
ON (wp_posts.ID = wp_term_relationships.object_id)
INNER JOIN wp_postmeta
ON ( wp_posts.ID = wp_postmeta.post_id )
WHERE 1 = 1
AND ( wp_term_relationships.term_taxonomy_id IN (1890041) )
AND ( wp_postmeta.meta_key = 'anyx-training-order' )
AND ((wp_posts.post_type = 'anyx-training'
AND (wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'complete'
OR wp_posts.post_status = 'private')))
GROUP BY wp_posts.ID
ORDER BY min_meta_value ASC;