【问题标题】:Query for transitive word translation查询及物词翻译
【发布时间】:2018-12-17 02:55:52
【问题描述】:

我在构建我猜应该是 CTE 查询时遇到问题,它会返回一个单词翻译。

我有两张桌子 - 单词:

ID | WORD | LANG
1   'Cat'   'ENG'
2   'Kot'   'POL'
3   'Katze' 'GER'

和连接:

ID | WORD_A | WORD_B
1       1         2
2       1         3

由于已经存在 ENG->POL 和 ENG->GER 翻译,我希望收到 POL->GER 翻译。

所以对于任何给定的单词,我必须检查它的连接翻译,如果目标语言不存在,我应该检查这些连接翻译的连接翻译等,直到找到任何一个翻译,或者什么都不返回;

我不知道从哪里开始,如果需要恒定数量的转换不会有问题,但它可能需要像 POL->ITA->...->ENG-> 这样的转换德国。

【问题讨论】:

  • 在连接表中要么是 1-3 要么是 POL->GER 已经存在???哪个是正确的??
  • 这需要递归 CTE。您使用的是什么版本的 SQLite?
  • @nikhilsugandh 表中有错误,如前所述 POLENG 和 ENGGER 连接仅存在
  • @novarek 这就是我说的!!!我第二次更正了!!!!!!
  • @GordonLinoff 版本 3.23.1

标签: sql sqlite


【解决方案1】:

这是一个复杂的图行走问题。这个想法是建立一个connections2 关系,在两个方向都有单词和语言,然后用它来遍历图表。

要获得波兰语单词的所有德语翻译,您可以使用:

with words AS (
      select 1 as id, 'Cat' as word, 'ENG' as lang union all
      select 2, 'Kot', 'POL' union all
      select 3, 'Katze', 'GER'
     ),
     connections as (
      select 1 as id, 1 as word_a, 2 as word_b union all
      select 2 as id, 1 as word_a, 3 as word_b
     ),
     connections2 as (
      select c.word_a as id_a, c.word_b as id_b, wa.lang as lang_a, wb.lang as lang_b
      from connections c join
           words wa
           on c.word_a = wa.id join
           words wb
           on c.word_b = wb.id
      union  -- remove duplicates
      select c.word_b, c.word_a, wb.lang as lang_a, wa.lang as lang_b
      from connections c join
           words wa
           on c.word_a = wa.id join
           words wb
           on c.word_b = wb.id
     ),
     cte as (
      select id as pol_word, id as other_word, 'POL' as other_lang, 1 as lev, ',POL,' as langs
      from words
      where lang = 'POL'
      union all
      select cte.pol_word, c2.id_b, c2.lang_b, lev + 1, langs || c2.lang_b || ','
      from cte join
           connections2 c2
           on cte.other_lang = c2.lang_a
      where langs not like '%,' || c2.lang_b || ',%' or c2.lang_b = 'GER'
     ) 
select *
from cte
where cte.other_lang = 'GER';

Here 是一个 dbfiddle。

大概,你想要最短的路径。为此,您将使用此查询(在 CTE 之后):

select *
from cte
where cte.other_lang = 'GER' and
      cte.lev = (select min(cte2.lev) from cte cte2 where ct2.pol_word = cte.pol_word);

【讨论】:

    【解决方案2】:

    我建议将您的表格设计更改为以下内容:

    ID | WORD_ID | WORD    | LANG
    1  | 1       | 'Cat'   | 'ENG'
    2  | 1       | 'Kot'   | 'POL'
    3  | 1       | 'Katze' | 'GER'
    

    现在假设您想从波兰语转到德语,并且从波兰语中的猫词Kot 开始。然后,您可以使用以下查询:

    SELECT t2.WORD
    FROM yourTable t1
    INNER JOIN yourTable t2
        ON t1.WORD_ID = t1.WORD_ID AND t2.LANG = 'GER'
    WHERE
        t1.WORD = 'Kot' AND t1.LANG = 'POL'
    

    Demo

    这里的想法是,您希望您的一个表维护每个逻辑上不同的单词到某个公共 id 或引用的映射。然后,您只需要输入的单词和语言,以及所需的输出语言,就可以进行映射。

    注意:为简单起见,我只展示了一个包含多种语言的单个单词的表格,但逻辑仍应适用于多种单词和语言。您当前的表格可能未标准化,但优化这可能是与您的直接问题不同的另一项任务。

    【讨论】:

    • 我有一个类似的方法开始,但有一个小问题:我没有有限的语言集,并且翻译是从 google api 接收的。当用户尝试将 cat - 'Gatto' (ITA) 翻译成 'Neko' (JAP) 时,会出现两个新的翻译,但我怎么知道应该将它们添加到哪个 WORD_ID?
    • 您是说作为最终用户使用 Google API 来填充您的表格吗?你能详细说明你在这里实际做什么吗?
    • 一个小型的个人使用项目来学习 Qt - 桌面谷歌翻译客户端,具有缓存功能 - 我希望存储以前请求的翻译,并连接不同语言的相同单词。
    • 当然,如果更改数据库架构是可以接受的,那么您的解决方案就完美了!
    猜你喜欢
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 2021-04-13
    • 2013-04-23
    • 1970-01-01
    • 1970-01-01
    • 2021-06-23
    • 1970-01-01
    相关资源
    最近更新 更多