MySQL多表关联查询指定语言排序异常问题求助
你的问题出在DISTINCT和ORDER BY的组合逻辑上。当你使用DISTINCT ProductID时,数据库会返回每个唯一的ProductID,但对于ORDER BY里的productsml.LanguageID和productsml.ProductName,数据库会从与该ProductID匹配的所有productsml行中随机选取一行来进行排序判断——这就导致当你指定LanguageID=2或3时,排序用的可能还是LanguageID=1的那行数据,自然结果和LanguageID=1时完全一致。
另外注意你的WHERE条件里写的products.ProductName LIKE '%а%',结合你的表结构来看,应该是笔误,实际要搜索的是多语言表的产品名称,建议改为productsml.ProductName LIKE '%а%',这样才能覆盖所有语言的搜索范围。
要实现你的需求——所有匹配的ProductID唯一,同时按指定LanguageID对应的ProductName排序,你需要先为每个ProductID绑定指定语言的ProductName,再基于这个值排序。这里提供两种可行方案:
方案1:用LEFT JOIN绑定指定语言名称
通过LEFT JOIN把指定LanguageID的productsml行关联进来,让每个ProductID对应唯一的目标语言名称,再基于这个名称排序:
SELECT DISTINCT p.ProductID FROM products p JOIN productsml pm ON p.ProductID = pm.ProductID -- 关联指定语言的产品名称行,这里把2替换成你需要的LanguageID LEFT JOIN productsml pm_target ON p.ProductID = pm_target.ProductID AND pm_target.LanguageID = 2 WHERE p.ProductIsActive = 1 AND pm.ProductName LIKE '%а%' -- 搜索所有语言的产品名称 ORDER BY -- 确保有指定语言翻译的行优先(如果存在的话) CASE WHEN pm_target.ProductName IS NOT NULL THEN 0 ELSE 1 END, pm_target.ProductName ASC;
方案2:用窗口函数(更灵活,推荐)
利用ROW_NUMBER()窗口函数为每个ProductID标记优先级,确保排序时使用指定语言的ProductName:
SELECT ProductID FROM ( SELECT p.ProductID, pm_target.ProductName AS target_name, -- 为指定语言的行标记最高优先级 ROW_NUMBER() OVER (PARTITION BY p.ProductID ORDER BY CASE WHEN pm.LanguageID = 2 THEN 0 ELSE 1 END) AS rn FROM products p JOIN productsml pm ON p.ProductID = pm.ProductID -- 关联指定语言的产品名称行,替换2为目标LanguageID LEFT JOIN productsml pm_target ON p.ProductID = pm_target.ProductID AND pm_target.LanguageID = 2 WHERE p.ProductIsActive = 1 AND pm.ProductName LIKE '%а%' ) AS sub WHERE rn = 1 -- 确保每个ProductID只返回一行 ORDER BY target_name ASC;
当指定LanguageID=2时,上述查询会基于每个ProductID对应的俄语ProductName排序,得到你预期的结果:
| ProductID |
|---|
| 2 |
| 1 |
| 3 |
同理,将LanguageID替换为3时,会按土耳其语ProductName排序,得到对应的预期结果。如果需要在结果中展示目标语言的名称和LanguageID,只需要在SELECT语句中添加pm_target.LanguageID, pm_target.ProductName即可。
内容的提问来源于stack exchange,提问作者Shapi

