接口 500,本地 debug 轻松地发现了问题:是 Mapper 中的一条 SQL 有问题,Column 'short_name' in order clause is ambiguous
SQL并不复杂,数据库结构就不赘述了,四张表连接查询。直接看问题 SQL:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
SELECT p.*, lt.NAME AS province_name, t.NAME country_name FROM sm_basic_province p LEFT JOIN sm_basic_country bc ON p.country = bc.country_id LEFT JOIN sm_basic_lang_tag t ON bc.NAME = t.tag_id AND t.lang = 1 AND t.tenant_id = 'keycai' LEFT JOIN sm_basic_lang_tag lt ON p.NAME = lt.tag_id AND lt.lang = 1 AND lt.tenant_id = 'keycai' WHERE p.tenant_id = 'keycai' AND bc.tenant_id = 'keycai' ORDER BY CONVERT ( short_name USING gbk ) DESC
问题很明显、很常见,short_name 字段名不明确。
错误解决
常规方法 ORDER BY 之前的查询结果加括号:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
(SELECT p.*, lt.NAME AS province_name, t.NAME country_name FROM sm_basic_province p LEFT JOIN sm_basic_country bc ON p.country = bc.country_id LEFT JOIN sm_basic_lang_tag t ON bc.NAME = t.tag_id AND t.lang = 1 AND t.tenant_id = 'keycai' LEFT JOIN sm_basic_lang_tag lt ON p.NAME = lt.tag_id AND lt.lang = 1 AND lt.tenant_id = 'keycai' WHERE p.tenant_id = 'keycai' AND bc.tenant_id = 'keycai') ORDER BY CONVERT ( short_name USING gbk ) DESC
错误依旧,SELECT * (…) t 生成中间表 t,再根据 t 表的 short_name 字段进行排序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
SELECT * FROM (SELECT p.*, lt.NAME AS province_name, t.NAME country_name FROM sm_basic_province p LEFT JOIN sm_basic_country bc ON p.country = bc.country_id LEFT JOIN sm_basic_lang_tag t ON bc.NAME = t.tag_id AND t.lang = 1 AND t.tenant_id = 'keycai' LEFT JOIN sm_basic_lang_tag lt ON p.NAME = lt.tag_id AND lt.lang = 1 AND lt.tenant_id = 'keycai' WHERE p.tenant_id = 'keycai' AND bc.tenant_id = 'keycai') t ORDER BY CONVERT ( short_name USING gbk ) DESC
SELECT p.*, lt.NAME AS province_name, t.NAME country_name FROM sm_basic_province p LEFT JOIN sm_basic_country bc ON p.country = bc.country_id LEFT JOIN sm_basic_lang_tag t ON bc.NAME = t.tag_id AND t.lang = 1 AND t.tenant_id = 'keycai' LEFT JOIN sm_basic_lang_tag lt ON p.NAME = lt.tag_id AND lt.lang = 1 AND lt.tenant_id = 'keycai' WHERE p.tenant_id = 'keycai' AND bc.tenant_id = 'keycai' ORDER BY short_name DESC
正确执行。
正常来讲一条 SQL 的执行顺序是:
1 2
FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY -> LIMIT 每步执行都会产生一个虚表,作为当前执行步骤的输出和下一步执行时的输入,只有当最后一步执行完后这个虚表才会作为这条被执行 SQL 的最终结果。