我在构建应该为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->德国。
答案 0 :(得分:0)
我建议将您的餐桌设计更改为以下几行:
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'
这里的想法是,您希望其中一个表维护每个逻辑上不同的单词到某个常见ID或引用的映射。然后,您只需要输入单词和语言以及所需的输出语言即可进行映射。
注意:为简单起见,我只显示一种表,其中包含几种语言中的单个单词,但逻辑仍应适用于多种单词和语言。您当前的表格可能未进行规范化,但优化可能是与您当前的问题分开的另一项任务。
答案 1 :(得分:0)
这是一个复杂的图形行走问题。这个想法是建立一个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是db <>小提琴。
大概,您需要最短的路径。为此,您可以使用此查询(在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);