我有那种字符串
测试1 |纽约| X,测试2 |芝加哥| Y,测试3 |哈里斯堡,巴勒斯坦ž
我要求的结果是
Column1 Column 2 Column3
Test 1 new york X
Test 2 chicago Y
Test 3 harrisburg,pa Z
但是运行此查询
SELECT
split_part(stat.st, '|', 1) Column1,
split_part(stat.st, '|', 2) Column2,
split_part(stat.st, '|', 3) Column3
FROM
(
SELECT
UNNEST (
string_to_array('Test 1|new york| X, Test 2| chicago|Y, Test 3| harrisburg, pa| Z',',')
)
AS st
) stat;
结果是
Column1 Column 2 Column3
Test 1 new york X
Test 2 chicago Y
Test 3 harrisburg
pa Z
Column3可以是一切(除了|)。匹配它的可能模式。这可以重复N次。除了|之外,STRING可以是一切焦炭。
我如何使用regexp_split_to_array()
来设置我的欲望结果?
答案 0 :(得分:3)
几乎没有足够的信息来完成这项工作。但是这样做了:
SELECT * FROM crosstab3(
$$
SELECT (rn/3)::text AS x, (rn%3)::text, item
FROM (
SELECT row_number() OVER () - 1 AS rn, trim(item) AS item
FROM (
SELECT CASE WHEN rn%2 = 1 THEN regexp_split_to_table(item, ',')
ELSE item END AS item
FROM (
SELECT row_number() OVER () AS rn, *
FROM regexp_split_to_table('Test 1|new york| X, Test 2| chicago|Y, Test 3| harrisburg, pa| Z', '\|') AS item
) x
) y
) z
$$)
返回:
row_name | category_1 | category_2 | category_3
----------+------------+----------------+------------
0 | Test 1 | new york | X
1 | Test 2 | chicago | Y
2 | Test 3 | harrisburg, pa | Z
在|
分割字符串后,我建立了一个标准,即只有不均匀行号的行应在,
分割。
我trim()
结果并添加另一个row_number()
的衍生物,以便在进行交叉制表之前到达此中间状态:
x | text | item
---+------+----------------
0 | 0 | Test 1
0 | 1 | new york
0 | 2 | X
1 | 0 | Test 2
1 | 1 | chicago
1 | 2 | Y
2 | 0 | Test 3
2 | 1 | harrisburg, pa
2 | 2 | Z
最后,我应用tablefunc
模块中的crosstab3()
函数。要安装它,如果您还没有:
CREATE EXTENSION tablefunc;
regexp_replace()
这是一个可能更容易理解的替代方案。不确定哪个更快。复杂的正则表达式往往很昂贵:
SELECT trim(split_part(a,'|', 1)) AS column1
,trim(split_part(a,'|', 2)) AS column2
,trim(split_part(a,'|', 3)) AS column3
FROM (
SELECT unnest(
string_to_array(
regexp_replace('Test 1|new york| X, Test 2| chicago|Y, Test 3| harrisburg, pa| Z'
,'([^|]*\|[^|]*\|[^,]*),', '\1~^~', 'g'), '~^~')) AS a
) sub
这个只在两个管道(,
)之后替换逗号(|
),然后继续。
现在使用*
而不是+
来允许管道之间的空字符串。