【问题标题】:SQL Query to replace multiple values in template from many-to-many tableSQL查询从多对多表中替换模板中的多个值
【发布时间】:2019-06-19 09:58:16
【问题描述】:

我想在一个 sql 查询中翻译一个模板。假设有以下四个表:state、stateProperty、state_stateproperty 和 translation:

state_stateproperty

|---------------------|--------------------|
|      state_id       | stateproperties_id |
|---------------------|--------------------|
|          1          |        2           |
|---------------------|--------------------|
|          1          |        3           |
|---------------------|--------------------|

状态属性

|---------------------|------------------|
|  id  |     key      |      value       |
|------|--------------|------------------|
|  2   | ${firstName} |      John        |
|------|--------------|------------------|
|  3   | ${lastName}  |      Doe         |
|------|--------------|------------------|

状态

|---------------------|
|  id  |  template    |
|------|--------------|
|  1   |  template    |
|------|--------------|

翻译

|------------|--------------|---------------------------------|
|  language  |  messageId   |             value               |
|------------|--------------|---------------------------------|
|  en        |  template    | ${lastName}, ${firstName} alarm |
|------------|--------------|---------------------------------|

目的是获得一个名为 translatestate 的新实体,其中包含状态的已翻译模板。在这个例子中,翻译后的模板看起来像:“Doe, John alarm”。如何在原生 sql 中连接多对多表,并将状态模板与其相关状态属性的值进行转换?

【问题讨论】:

    标签: sql postgresql replace many-to-many


    【解决方案1】:

    说实话,我会创建一个小函数,在其中循环遍历您的 state_property 并将找到的通配符字符串累积替换为其文本。


    但是我在一个查询中解决了这个问题。我不确定它是否匹配所有特殊情况,但对于您的示例,它可以工作:

    demo:db<>fiddle

    SELECT
        string_agg(                                                           -- 8
            regexp_replace(split_key, '^.*\}', value),                        -- 7
            '' ORDER BY row_number
        )
    FROM (
        SELECT
            s.id,
            sp.value,
            substring(key, 3) as s_key,                                       -- 5
            split_table.*
        FROM translation t
        JOIN statechange sc ON t.messageid = sc.completemessagetemplateid     -- 1
        JOIN state s ON s.id = sc.state_id
        JOIN state_stateproperty ssp ON s.id = ssp.state_id
        JOIN stateproperty sp ON ssp.stateproperties_id = sp.id
        JOIN translation stnme ON s.nameid = stnme.messageid
        CROSS JOIN                                        
            regexp_split_to_table(                                            -- 3   
                -- 2
                replace(t.messagetranslation, '${state}', stnme.messagetranslation),
                '\$\{'
            ) WITH ORDINALITY as split_table(split_key, row_number)           -- 4
        WHERE t.language = 'en'
    ) s
    WHERE position(s_key in split_key) = 0 and split_key != ''                -- 6
    GROUP BY id                                                               -- 8
    
    1. 简单地将表连接在一起(下次您可以稍微简化您的示例,这样我们就不必创建这些不同的表。我相信您知道如何连接)
    2. 很难将${state} 变量替换为状态nameid
    3. 每次找到${ 字符串时都会拆分模板字符串。因此它创建了一个以某个通配符开头的新行。请注意,${firstName} 将变为 firstName},因为正在删除字符串分隔符。
    4. 添加行计数以获得标准,当我稍后聚合行时 (8)。 WITH ORDINALITY 仅作为 FROM 子句的一部分使用,因此它的整个函数已通过连接添加到此处。
    5. 因为 (3) 我也从键中剥离了 ${ 部分。所以以后可以更好的解析和比较(在6中)
    6. 因为 (3) 创建了太多行(交叉连接),我只想要 key 是拆分字符串的第一个通配符的这些行。其他人都错了。
    7. 现在我用这个键替换通配符
    8. 因为我们每行只有一个通配符,我们需要将它们再次合并为一个字符串(按state_id 分组)。实现正确的顺序,我们使用的是(5)中的行号

    【讨论】:

    • @unrated 这有帮助吗?如果是这样,请不要忘记投票(它以一些内部可信度来表彰作者为您所做的工作)。如果它不仅有帮助而且完全正确,您应该接受。这表明他们不需要做任何工作,因为你的问题已经解决了。
    • 由于我的查询要大得多,我试图将您的查询整合到我的查询中。但直到现在我无法让它工作。错误:t.value 列不存在第 22 行:regexp_split_to_table(t.value, '\$\{') as split_key, 提示:也许您的意思是引用列“sp.value”。
    • 错误信息告诉你到底是什么问题:没有别名 t 的列。在我的示例中, t 用于表格翻译。也许你有另一个别名?
    • 我了解错误消息,但我只是将您的确切查询复制到我的中。也许我应该更新我的帖子并添加我的完整查询。
    • 啊,我明白了。这都是我的错。在通过表格展开之前使用了 row_number() 函数。因此,在展开后,所有元素都获得了相同的行号,因此聚合以随机顺序进行。现在,为了避免子查询,我使用 WITH ORDINALITY 功能(我认为这是有史以来第一次 :D)来创建行号。现在看起来不错。
    猜你喜欢
    • 2010-12-27
    • 1970-01-01
    • 1970-01-01
    • 2015-05-21
    • 2011-03-25
    • 1970-01-01
    • 2020-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多