[英]Postgresql subtract comma separated string in one column from another column
The format is like:格式如下:
col1 ![]() |
col2 ![]() |
---|---|
V1,V2,V3,V4,V5,V6 ![]() |
V4,V1,V6 ![]() |
V1,V2,V3 ![]() |
V2,V3 ![]() |
I want to create another column called col3 which contains the subtraction of two columns.我想创建另一个名为 col3 的列,其中包含两列的减法。
What I have tried:我试过的:
UPDATE myTable
SET col3=(replace(col1,col2,''))
It works well for rows like row2 since the order of replacing patterns matters.它适用于像 row2 这样的行,因为替换模式的顺序很重要。
I was wondering if there's a perfect way to achieve the same goal for rows like row1.我想知道是否有一种完美的方法可以为 row1 之类的行实现相同的目标。
So the desired output would be:所以所需的输出将是:
col1 ![]() |
col2 ![]() |
col3 ![]() |
---|---|---|
V1,V2,V3,V4,V5,V6 ![]() |
V4,V1,V6 ![]() |
V2,V3,V5 ![]() |
V1,V2,V3 ![]() |
V2,V3 ![]() |
V1 ![]() |
Any suggestions would be appreciated!任何建议,将不胜感激!
Split values into tables, subtract sets and then assemble it back.将值拆分为表格,减去集合,然后将其组合回来。 Everything is possible as an expression defining new query column.
一切都可以作为定义新查询列的表达式。
with t (col1,col2) as (values
('V1,V2,V3,V4,V5,V6','V4,V1,V6'),
('V1,V2,V3','V2,V3')
)
select col1,col2
, (
select string_agg(v,',')
from (
select v from unnest(string_to_array(t.col1,',')) as a1(v)
except
select v from unnest(string_to_array(t.col2,',')) as a2(v)
) x
)
from t
You will have to unnest the elements then apply an EXCEPT clause on the "unnested" rows and aggregate back:您必须取消嵌套元素,然后在“未嵌套”行上应用 EXCEPT 子句并聚合回来:
select col1,
col2,
(select string_agg(item,',' order by item)
from (
select *
from string_to_table(col1, ',') as c1(item)
except
select *
from string_to_table(col2, ',') as c2(item)
) t)
from the_table;
I wouldn't store that result in a separate column, but if you really need to introduce even more problems by storing another comma separated list.我不会将该结果存储在单独的列中,但如果您确实需要通过存储另一个逗号分隔列表来引入更多问题。
update the_table
set col3 = (select string_agg(item,',' order by item)
from (
select *
from string_to_table(col1, ',') as c1(item)
except
select *
from string_to_table(col2, ',') as c2(item)
) t)
;
string_to_table()
requires Postgres 14 or newer. string_to_table()
需要 Postgres 14 或更高版本。 If you are using an older version, you need to use unnest(string_to_array(col1, ','))
instead如果您使用的是旧版本,则需要使用
unnest(string_to_array(col1, ','))
代替
If you need that a lot, consider creating a function:如果您需要很多,请考虑创建一个函数:
create function remove_items(p_one text, p_other text)
returns text
as
$$
select string_agg(item,',' order by item)
from (
select *
from string_to_table(col1, ',') as c1(item)
except
select *
from string_to_table(col2, ',') as c2(item)
) t;
$$
language sql
immutable;
Then the above can be simplified to:那么上面的可以简化为:
select col1, col2, remove_items(col1, col2)
from the_table;
Note, POSTGRESQL
is not my forte, but thought I'd have a go at it.请注意,
POSTGRESQL
不是我的强项,但我想我会尝试一下。 Try:尝试:
SELECT col1, col2, RTRIM(REGEXP_REPLACE(Col1,CONCAT('\m(?:', REPLACE(Col2,',','|'),')\M,?'),'','g'), ',') as col3 FROM myTable
The idea is to use a regular expession to replace all values, based on following pattern:这个想法是使用常规表达式来替换所有值,基于以下模式:
\m
- Word-boundary at start of word; \m
- 单词开头的单词边界;(?:V4|V1|V6)
- A non-capture group that holds the alternatives from col2; (?:V4|V1|V6)
- 一个非捕获组,包含 col2 的备选方案;\M
- Word-boundary at end of word; \M
- 词尾的词边界;,?
- Optional comma. When replaced with nothing we need to clean up a possible trailing comma with RTRIM()
.当替换为空时,我们需要使用
RTRIM()
清理可能的尾随逗号。 See an online demo where I had to replace the word-boundaries with the \b
word-boundary to showcase the outcome.请参阅在线演示,我必须将单词边界替换为
\b
单词边界以展示结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.