多自连接查询重复问题求助:构建ERRMSG表翻译表遇异常
问题分析与解决方案
你的重复问题根源在于用了整个ERRMSG表作为主表(X),再做多次FULL JOIN——因为ERRMSG里每个MSGKEY+MSGNUM对应多行不同语言的数据,每一行都会作为X去匹配其他语言的表,最终同一个MSGKEY+MSGNUM会被多次输出,导致重复。
举个例子:如果某个MSGKEY+MSGNUM有L1和L2两条记录,那么X会先取L1的行去关联L1/L2/L3/L4表,得到一行结果;接着X又会取L2的行去关联同样的表,又得到一行内容几乎一样的结果,这就是重复的原因。
下面给你两种高效的解决办法:
方法一:基于唯一键集合的LEFT JOIN
先提取所有唯一的MSGKEY+MSGNUM组合作为基础表,再分别关联各语言的记录,确保每个组合只输出一次:
SELECT base.MSGKEY, base.MSGNUM, ISNULL(L1.MESSAGE, '') AS L1TEXT, ISNULL(L2.MESSAGE, '') AS L2TEXT, ISNULL(L3.MESSAGE, '') AS L3TEXT, ISNULL(L4.MESSAGE, '') AS L4TEXT FROM -- 先获取所有唯一的消息键值对 (SELECT DISTINCT MSGKEY, MSGNUM FROM ERRMSG) base -- 左连接各语言表,确保即使某语言无数据也能保留空字符串 LEFT JOIN ERRMSG L1 ON base.MSGKEY = L1.MSGKEY AND base.MSGNUM = L1.MSGNUM AND L1.LANGU = 'L1' LEFT JOIN ERRMSG L2 ON base.MSGKEY = L2.MSGKEY AND base.MSGNUM = L2.MSGNUM AND L2.LANGU = 'L2' LEFT JOIN ERRMSG L3 ON base.MSGKEY = L3.MSGKEY AND base.MSGNUM = L3.MSGNUM AND L3.LANGU = 'L3' LEFT JOIN ERRMSG L4 ON base.MSGKEY = L4.MSGKEY AND base.MSGNUM = L4.MSGNUM AND L4.LANGU = 'L4'
方法二:用CASE WHEN+聚合函数(更高效)
这种方式只需要扫描一次表,通过分组和条件筛选直接生成多语言列,性能更优:
SELECT MSGKEY, MSGNUM, -- 用MAX聚合取出对应语言的消息(因为单语言下MSGKEY+MSGNUM唯一,MAX只会取到唯一值) MAX(CASE WHEN LANGU = 'L1' THEN MESSAGE ELSE '' END) AS L1TEXT, MAX(CASE WHEN LANGU = 'L2' THEN MESSAGE ELSE '' END) AS L2TEXT, MAX(CASE WHEN LANGU = 'L3' THEN MESSAGE ELSE '' END) AS L3TEXT, MAX(CASE WHEN LANGU = 'L4' THEN MESSAGE ELSE '' END) AS L4TEXT FROM ERRMSG -- 按消息键值对分组,把同一组合的多语言行聚合为一行 GROUP BY MSGKEY, MSGNUM
两种方法都能解决重复问题,推荐第二种,因为它的查询成本更低,代码也更简洁。
内容的提问来源于stack exchange,提问作者Ching
相关产品推荐
相关产品推荐

