替换文本表达式中的多个 ID
Replace multiple IDs within text expression
我已经查过了,之前没有发现这样的问题。
我有一个名为 tests
的 table,它(简化)包含 3 列。
| id | name | expression |
=========================================
| 1 | width | |
| 2 | length | |
| 3 | area | [1] * [2] |
我需要一个给定测试 ID 的查询可以 return 完全限定的表达式,即用相关名称替换表达式中的 ID 号。
表达式始终包含方括号内的 ID 号。
我走了几条路,但这是我当前的查询,但它不会将名称替换为一个字符串。
查询:
WITH regexmatch AS
(
SELECT
id,
expression,
(regexp_matches(expression, '\[(\d+)\]', 'g'))[1] AS replaceid
FROM
test
WHERE
expression IS NOT NULL
AND
id = 3
GROUP BY
id, expression
)
SELECT
regexmatch.id,
regexmatch.expression,
REPLACE(regexmatch.expression, replaceid, (SELECT name FROM test WHERE id = replaceid::bigint))
FROM
regexmatch
输出:
| id | expression | replacement |
================================================
| 1 | [1] * [2] | [width] * [2] |
| 2 | [1] * [2] | [1] * [length] |
这个查询是否可行?如果可行,我应该怎么做?
一种方式是递归常用table表达式:
CREATE TABLE test(id INT, "name" VARCHAR(100), expression VARCHAR(100));
INSERT INTO test(id, "name", expression)
SELECT 1, 'width', NULL
UNION ALL SELECT 2, 'length', NULL
UNION ALL SELECT 3, 'area' , '[1] * [2]'
UNION ALL SELECT 4, 'height', NULL
UNION ALL SELECT 5, 'volume', '[3] * [4]'
UNION ALL SELECT 6, 'volumne_alt', '[2]^3';
查询:
WITH RECURSIVE cte AS (
SELECT id, expression::varchar(10000), "name"
,(regexp_matches(expression, '\[(\d+)\]'))[1] AS repid
FROM test
WHERE expression IS NOT NULL
UNION ALL
SELECT id, REPLACE(expression, repid, (SELECT name
FROM test
WHERE id = repid::int))::varchar(10000)
,"name",(regexp_matches(expression, '\[(\d+)\]'))[1]
FROM cte c
WHERE c.expression ~ '(.*)\[(\d+)\](.*)'
)
SELECT id, "name", expression
FROM cte
WHERE expression !~ '(.*)\[(\d+)\](.*)'
ORDER BY id;
输出:
╔═════╦══════════════╦════════════════════╗
║ id ║ name ║ expression ║
╠═════╬══════════════╬════════════════════╣
║ 3 ║ area ║ [width] * [length] ║
║ 5 ║ volume ║ [area] * [height] ║
║ 6 ║ volumne_alt ║ [length]^3 ║
╚═════╩══════════════╩════════════════════╝
与table UPDATE
:
WITH cte AS
(...
)
UPDATE test AS t
SET expression = c.expression
FROM cte AS c
WHERE t.id = c.id AND c.expression !~ '(.*)\[(\d+)\](.*)';
输出:
╔═════╦══════════════╦════════════════════╗
║ id ║ name ║ expression ║
╠═════╬══════════════╬════════════════════╣
║ 1 ║ width ║ (null) ║
║ 2 ║ length ║ (null) ║
║ 3 ║ area ║ [width] * [length] ║
║ 4 ║ height ║ (null) ║
║ 5 ║ volume ║ [area] * [height] ║
║ 6 ║ volumne_alt ║ [length]^3 ║
╚═════╩══════════════╩════════════════════╝
我已经查过了,之前没有发现这样的问题。
我有一个名为 tests
的 table,它(简化)包含 3 列。
| id | name | expression |
=========================================
| 1 | width | |
| 2 | length | |
| 3 | area | [1] * [2] |
我需要一个给定测试 ID 的查询可以 return 完全限定的表达式,即用相关名称替换表达式中的 ID 号。
表达式始终包含方括号内的 ID 号。
我走了几条路,但这是我当前的查询,但它不会将名称替换为一个字符串。
查询:
WITH regexmatch AS
(
SELECT
id,
expression,
(regexp_matches(expression, '\[(\d+)\]', 'g'))[1] AS replaceid
FROM
test
WHERE
expression IS NOT NULL
AND
id = 3
GROUP BY
id, expression
)
SELECT
regexmatch.id,
regexmatch.expression,
REPLACE(regexmatch.expression, replaceid, (SELECT name FROM test WHERE id = replaceid::bigint))
FROM
regexmatch
输出:
| id | expression | replacement |
================================================
| 1 | [1] * [2] | [width] * [2] |
| 2 | [1] * [2] | [1] * [length] |
这个查询是否可行?如果可行,我应该怎么做?
一种方式是递归常用table表达式:
CREATE TABLE test(id INT, "name" VARCHAR(100), expression VARCHAR(100));
INSERT INTO test(id, "name", expression)
SELECT 1, 'width', NULL
UNION ALL SELECT 2, 'length', NULL
UNION ALL SELECT 3, 'area' , '[1] * [2]'
UNION ALL SELECT 4, 'height', NULL
UNION ALL SELECT 5, 'volume', '[3] * [4]'
UNION ALL SELECT 6, 'volumne_alt', '[2]^3';
查询:
WITH RECURSIVE cte AS (
SELECT id, expression::varchar(10000), "name"
,(regexp_matches(expression, '\[(\d+)\]'))[1] AS repid
FROM test
WHERE expression IS NOT NULL
UNION ALL
SELECT id, REPLACE(expression, repid, (SELECT name
FROM test
WHERE id = repid::int))::varchar(10000)
,"name",(regexp_matches(expression, '\[(\d+)\]'))[1]
FROM cte c
WHERE c.expression ~ '(.*)\[(\d+)\](.*)'
)
SELECT id, "name", expression
FROM cte
WHERE expression !~ '(.*)\[(\d+)\](.*)'
ORDER BY id;
输出:
╔═════╦══════════════╦════════════════════╗
║ id ║ name ║ expression ║
╠═════╬══════════════╬════════════════════╣
║ 3 ║ area ║ [width] * [length] ║
║ 5 ║ volume ║ [area] * [height] ║
║ 6 ║ volumne_alt ║ [length]^3 ║
╚═════╩══════════════╩════════════════════╝
与table UPDATE
:
WITH cte AS
(...
)
UPDATE test AS t
SET expression = c.expression
FROM cte AS c
WHERE t.id = c.id AND c.expression !~ '(.*)\[(\d+)\](.*)';
输出:
╔═════╦══════════════╦════════════════════╗
║ id ║ name ║ expression ║
╠═════╬══════════════╬════════════════════╣
║ 1 ║ width ║ (null) ║
║ 2 ║ length ║ (null) ║
║ 3 ║ area ║ [width] * [length] ║
║ 4 ║ height ║ (null) ║
║ 5 ║ volume ║ [area] * [height] ║
║ 6 ║ volumne_alt ║ [length]^3 ║
╚═════╩══════════════╩════════════════════╝