【问题标题】:MySQL pivot table for Multilingual Dictionary [duplicate]多语言词典的MySQL数据透视表[重复]
【发布时间】:2016-07-20 15:23:15
【问题描述】:

我的表结构如下所示:

如您所见,它是一个多语言字典,每种语言的所有值都存储在同一张表中,重复“键”值。

我想要的是一个 SQL 语句来获取具有唯一“键”的所有行,包括每种语言的“值”列。

我到目前为止所尝试的,它只适用于两种语言,仅此而已:

select a.*, b.value
from `translator_messages` a 
JOIN `translator_messages` b
on a.key = b.key and
a.lang !=b.lang
group by a.key

结果:

注意:最好有一个通用的 SQL 解决方案,而不是依赖于 MySQL 的特定功能。

【问题讨论】:

  • 请提供样本结果。
  • 这看起来像您当前查询可能生成的结果,而不是根据样本数据您想要的输出。
  • 如您所见,结果仅包含两种语言的“值”列。根据样本数据,缺少“de-GE”语言的值列。可能包括更多语言。
  • 只是不清楚您使用什么逻辑来获得这些结果。你想让它任意选择一个语言记录,以及任意两个value的?

标签: mysql sql join self-join


【解决方案1】:

如果你想要只出现一次的键,那么你可以使用not exists:

select tm.*
from translator_messages tm
where not exists (select 1
                  from translator_messages tm2
                  where tm2.key = tm.key and tm2.id <> tm.id
                 );

或者,如果您只想将每个键的所有值放在一列中:

select tm.key, group_concat(value separator '|') as values
from translator_messages tm;

这会将所有值放在一个列中。如果您愿意,您甚至可以指定语言:

select tm.key, group_concat(lang, ':', value separator '|') as values
from translator_messages tm;

【讨论】:

  • Mysql 返回一个空的结果集!
  • @Hamed 第一个查询返回一个空集,因为您的所有键都不会只出现一次。我猜你对GROUP_CONCAT() 选项感兴趣。
  • 未连接的值是必需的。应用程序需要单独的值。
【解决方案2】:

不要使用GROUP BY a.key,因为它只为每个键显示一行,而不是所有的翻译。如果您想同时查看同一键的所有翻译,但在单独的行中,请使用 ORDER BY a.key

您可能还想将a.lang != b.lang 更改为a.lang &lt; b.lang。当前查询将显示同一对行两次,一次用于a.lang = en-USb.lang = fa-IR,然后再次用于a.lang = fa-IRb.lang = en-US。使用 &lt; 而不是 ! 使它只显示第一对。

【讨论】:

  • 将 != 替换为
  • 什么重复?编辑您的问题并显示您想要获得的输出。
【解决方案3】:

您需要dynamic pivot table 来完成此操作。

SET @sql := NULL;

SELECT
    GROUP_CONCAT(t.output) INTO @sql
FROM
    (
        SELECT
            CONCAT(
                'MAX(CASE WHEN lang=\'',
                lang,
                '\' THEN `value` END) AS ',
                CONCAT(REPLACE (lang, '-', '_'),'_value')
            ) output
        FROM
            translator_messages
        GROUP BY
            lang
    ) AS t;


SET @SQL := CONCAT(
    'SELECT `key`,category,' ,@SQL,
    ' FROM translator_messages GROUP BY `key`'
);

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

WORKING DEMO

示例输入:

| id |  lang | category |   key | value |
|----|-------|----------|-------|-------|
|  1 | en-US |      app |  book |    v1 |
|  2 | fa-IR |      app |  book |    v2 |
|  3 | de-GE |      app |  book |    v3 |
|  4 | en-US |      app | salad |    v4 |
|  5 | fa-IR |      app | salad |    v5 |
|  6 | de-GE |      app | salad |    v6 |

样本输出(由上述查询生成):

|   key | category | de_GE_value | en_US_value | fa_IR_value |
|-------|----------|-------------|-------------|-------------|
|  book |      app |          v3 |          v1 |          v2 |
| salad |      app |          v6 |          v4 |          v5 |

注意:

注意字符串变量和 GROUP_CONCAT 的 MySQL 最大大小。

如果 GROUP_CONCAT 最大长度是限制(默认为 1024),您应该 更改其长度的临时设置(会话范围)。它是 完成者:

设置会话 group_concat_max_len = 10000

Set group_concat_max_len permanently (MySQL config)

【讨论】:

  • 哇,终于找到了一个可行的解决方案。谢谢。我从来没有想过它会变得如此复杂!第一次使用mysql语句,学习中……
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-22
  • 1970-01-01
  • 2021-10-09
  • 1970-01-01
相关资源
最近更新 更多