Need help in parsing column value based on value in other column
我有两列,COL1 和 COL2。 COL1 的值类似于 'Birds sitting on $1 and enjoying',COL2 的值类似于 'the.location_value[/tree,\\building]'
我需要用 'Birds sitting on /tree and enjoying'
之类的值更新第三列 COL3
即第一列中的 $1 替换为 /tree
这是逗号分隔的单词列表中的第一个单词,在 COL2 中带有方括号 [],即 [/tree,\\building]
我想知道 postgresql 中最合适的字符串函数组合来实现这一点。
- 为什么要存储已经在 COL1 和 COL2 中的信息?
-
对于报告工具。它不是很重要。但是如何查询是我想知道的。谢谢。
您需要首先从逗号分隔列表中提取第一个元素,为此,您可以使用 split_part() 但您首先需要提取实际的值列表。这可以使用带有正则表达式的 substring() 来完成:
1
| SUBSTRING(col2 FROM '\\[(.*)\\]') |
将返回 /tree,\\building
所以完整的查询是:
1 2
| SELECT REPLACE(col1, '$1', split_part(SUBSTRING(col2 FROM '\\[(.*)\\]'), ',', 1))
FROM the_table; |
在线示例:http://rextester.com/CMFZMP1728
- 如何在评论栏中按回车键。我一按回车键,它就会发表评论!
-
在 psql (9.6.2) 中工作正常,但在 psql (9.5.1) 中不工作 - select substring(the.location_value[/tree,\\\\\\\\building] from (.*));警告:在字符串文字中非标准使用转义 ^ 提示:使用转义字符串语法进行转义,例如,E\\\\
\\\\
.警告:在字符串文字第 1 行中对转义的非标准使用: ...string(the.location_value[/tree,\\\\\\\\building] from (.*)... ^ 提示:使用转义字符串语法进行转义,例如,E\\\\
\\\\
.
-
这听起来好像您在 9.5 安装中已将 set standard_conforming_strings 设置为 "off"。它适用于默认的 9.5 安装(在线示例使用 9.5.3)。我强烈建议将 standard_conforming_strings 设置为 ON(这是默认设置,因此您必须主动决定在 9.5 安装中使用非标准字符串)
-
你好谢谢。但我不能这样做,因为我没有这样做的权限。有没有其他方法可以查询结果。谢谢。
-
遵循错误消息"提示"部分给出的建议(但您应该真正询问负责人他们选择偏离标准的原因。这不是推荐的配置)
-
我在模式中添加了一个 \\\\\\\\ (开始时)并且它起作用了。谢谢。 select replace(col1, $1, split_part(substring(col2 from \\\\\\\\(.*)), ,, 1)) from mytable where itemid = 25908;
-
但是,问题是,如果 COL1 没有搜索字符串 $1,则查询不会返回任何内容。如果没有$ 1或$ 2等的测试,有没有办法获得结果,
-
如果文本有 2 美元,我也想获取第二个单词。谢谢。
这应该适用于 $:
之后的任何 (int) 数字
1 2 3 4 5 6 7
| SELECT t.*, c.col3
FROM t,
lateral (SELECT string_agg(CASE
WHEN o = 1 THEN s
ELSE (string_to_array((SELECT regexp_matches(t.col2, '\\[(.*)\\]'))[1], ','))[(SELECT regexp_matches(s, '^\\$(\\d+)'))[1]::INT] || SUBSTRING(s FROM '^\\$\\d+(.*)')
END, '' ORDER BY o) col3
FROM regexp_split_to_table(t.col1, '(?=\\$\\d+)') WITH ordinality s(s, o)) c |
http://rextester.com/OKZAG54145
注意:虽然它不是最有效的。它每次都拆分 col2 的值(在方括号中)以替换 $N.
更新:旧版本不支持 LATERAL 和 WITH ORDINALITY,但您可以尝试使用关联子查询:
1 2 3 4 5 6 7
| SELECT t.*, (SELECT array_to_string(array_agg(CASE
WHEN s ~ E'^\\\\$(\\\\d+)'
THEN (string_to_array((SELECT regexp_matches(t.col2, E'\\\\[(.*)\\\\]'))[1], ','))[(SELECT regexp_matches(s, E'^\\\\$(\\\\d+)'))[1]::INT] || SUBSTRING(s FROM E'^\\\\$\\\\d+(.*)')
ELSE s
END), '') col3
FROM regexp_split_to_table(t.col1, E'(?=\\\\$\\\\d+)') s) col3
FROM t |
-
如何在此查询中使用 where 子句。例如,如果我需要提及,WHERE T.ID = 125;
-
@anandgp 您可以使用 WHERE t.id = ... 或您要使用的选择的其他部分继续查询。
-
但它失败了 - 错误:在 "select" LINE 3 处或附近出现语法错误:横向(选择 string_agg(case
-
我正在这样做 - 从 mytable t 中选择 t.name, t.key_, c.col3,lateral (select string_agg(case when o = 1 then s else (string_to_array((select regexp_matches(t.key_, (.*)) )[1], ,))[(select regexp_matches(s, ^\\\\\\\\$(\\\\\\\\d )))[1]::int] || substring(s from ^\\\\\\\\$\\ \\\\\\d (.*)) end, order by o) col3 from regexp_split_to_table(t.name, (?=\\\\\\\\$\\\\\\\\d)) with ordinality s(s, o)) c where itemid = 25909;
-
@anandgp 你在某处有错字,我的查询适用于 WHERE:rextester.com/VSVKJ20607
-
存在如下转义字符串问题。但我用 \\\\\\\\\\\\\\\\ 纠正了它。警告:字符串文字中转义的非标准使用第 2 行:值(25909,坐在 $1 和 $2 上的鸟,the.location... ^ 提示:使用转义字符串语法进行转义,例如,E\\\\
\\\\
.错误:"select" 或附近的语法错误 LINE 6:lateral (select string_agg(case
-
但它仍然给我以下错误。我使用了你的新查询。错误:"select" 或附近的语法错误 LINE 6:lateral (select string_agg(case
-
与 mytable(itemid, name, key_) as ( values (25909, Birds sitting on $1 and $2, the.location_value[/tree,/building]) ) select t.name, t.key_, c.col3 from mytable t,横向 (select string_agg(case when o = 1 then s else (string_to_array((select regexp_matches(t.key_, \\\\\\\\(.*)))[1], ,))[(select regexp_matches(s, ^\\ \\\\\\$(\\\\\\\\d )))[1]::int] || substring(s from ^\\\\\\\\$\\\\\\\\d (.*)) end, order by o) col3 from regexp_split_to_table(t.name, (?=\\\\\\\\$\\\\\\\\d)) 与序数 s(s, o)) c where itemid = 25909;
-
@anandgp 它适用于示例,即 PostgreSQL 9.5。不要发布您的 psql 版本,因为那只是客户端版本。它在任何方面都没有帮助。 (使用 select version() 来确定服务器的版本)。
-
哦好的。谢谢。我的版本是 - x86_64-redhat-linux-gnu 上的 PostgreSQL 8.4.20
-
@anandgp 这解释了很多。请参阅我更新的答案,但请注意我无法使用旧 PostgreSQL 对其进行测试。 (但它应该可以工作:rextester.com/QVGLCF6870)
-
还没有运气 :( 错误:函数 string_agg(text, unknown) 不存在 LINE 4: select t.*, (select string_agg(case ^ HINT: No function matches the given name and argument types. You might need to add explicit type演员表。
-
@anandgp array_to_string(array_agg(...), ,) 应该在 8.4 而不是 string_agg(..., ,) 中可用 - 请参阅更新的答案。
-
我试过这个 - 使用 t(col1, col2) as ( values (EBirds 坐在 $1 和 $2, Ethe.location_value[/tree,\\\\\\\\\\\\\\\\building]) ) 选择 t.*, (select array_to_string( array_agg(case when s ~ E^\\\\\\\\\\\\\\\\$(\\\\\\\\\\\\\\\\d) then (string_to_array((select regexp_matches(t.col2, E\\\\\\\\(.*)\\ \\\\\\))[1], ,))[(选择正则表达式匹配(s, E^\\\\\\\\\\\\\\\\$(\\\\\\\\\\\\\\\\d)))[1]::int] || substring(s from E^\\\\\\\\\\\\\\\\$\\\\\\\\\\\\\\\\d (.*)) else s end, ,)) col3 from regexp_split_to_table(t.col1, E(?= \\\\\\\\\\\\\\\\$\\\\\\\\\\\\\\\\d )) s) col3 来自 t;
-
低于 - 错误:函数 array_agg(text, unknown) 不存在第 4 行:select t.*, (select array_to_string(array_agg(case ^ 提示:没有函数匹配给定的名称和参数类型。您可能需要添加显式类型演员表。
-
@anandgp array_agg 只有1个参数,请正确复制。
-
我们是否可以通过编写一个小函数来检查传递的文本中的任何 $n 来实现这个结果。如果没有 $n,它将简单地返回相同的文本。如果文本中有任何$n,它会使用多行代码解析并返回值吗?谢谢。
-
抱歉,我不明白。你能给我更新的查询吗?谢谢。
-
@anandgp 子查询正是这样做的。您可以将其提取到一个函数中,但这既不会提高性能,也不会提高可读性。 -- 答案已经有更新的查询。查看实际操作:rextester.com/FHRU91685
-
行。谢谢作品。非常感谢。非常感谢您的帮助。
-
这样可行。非常感谢。非常感谢您的帮助。