PostgreSQL字符串的一部分是在一个数组中

问题描述:

我想要获取值的哪些部分的ID是在一个定义的列表中。比方说,我们有一个称为表ABCPostgreSQL字符串的一部分是在一个数组中

CREATE TABLE abc 
AS 
    SELECT post_id 
    FROM (VALUES 
    ('868164246578472_912876412107255'), 
    ('868164246578472_912883258773237'), 
    ('868164246578472_913049595423270') 
) AS t(post_id); 

然后,我只取部分下划线

select (regexp_split_to_array(element_id, '_'))[2] as element_id from ABC limit 3; 
     element_id  
    ----------------- 
    912876412107255 
    912883258773237 
    913049595423270 

现在我想只拿那些元素,在那里他们element_ids是一个定义列表但后我没有得到任何结果

select (regexp_split_to_array(post_id, '_'))[2] as post_id from ABC where post_id = ANY('{912876412107255, 912883258773237}'::text[]) limit 3; 
post_id 
--------- 
(0 rows) 

我也试过这样:

select (regexp_split_to_array(post_id, '_'))[2]::text[] as post_id from ABC where post_id IN ('912876412107255', '912876412107255') limit 3; 
post_id 
--------- 
(0 rows) 

表的结构如下:

Table "public.ABC" 
    Column  |   Type    |      Modifiers      
---------------+-----------------------------+------------------------------------------------------ 
id   | integer      | not null default nextval('ABC_id_seq'::regclass) 
element_id | text      | not null 
+0

where子句? (不认为这是允许的) 此外,为什么只有1个元素时,将选定的表达式放入数组中。 –

+0

@JoeLove:这是不允许的。这就是为什么戈德里克失败的原因。 – kmkaplan

+1

是的,谢谢。我想通了,并立即发布答案 – Godric

OK,我刚刚找到了答案:

select (regexp_split_to_array(element_id, '_'))[2] as element_id from ABC where element_id similar to '%(912876412107255|912883258773237)%'; 
    element_id  
----------------- 
912876412107255 
912883258773237 
(2 rows) 
+0

添加'_'并删除尾部的'%'以获得更少的虚假匹配。如果某些'element_id'碰巧是你想要的前缀,你仍然可以得到一些。总结它的一个丑陋的解决方案。 – kmkaplan

+1

避免使用正则表达式函数。简单的字符串操作功能更便宜(更快)。 – klin

+0

也是整个SIMILAR TO是愚蠢的。它总是比正则表达式慢。而且,你知道整个ID是什么。那么为什么在将它分开后使用'%'? –

未经测试(从我的电话):

SELECT kmkid, element_id 
    FROM (SELECT (regexp_split_to_array(element_id, '_'))[2] as kmkid, element_id FROM ABC) 
    WHERE kmkid IN ('912876412107255', '912876412107255'); 

使用比正则表达式功能便宜得多的功能string_to_array()

您应该使用WHERE子句中的表达式:

select (string_to_array(post_id, '_'))[2] as post_id 
from abc 
where (string_to_array(post_id, '_'))[2] = any('{912876412107255, 912883258773237}'); 

或派生表:

select post_id 
from (
    select (string_to_array(post_id, '_'))[2] as post_id 
    from abc 
    ) s 
where post_id = any('{912876412107255, 912883258773237}'); 

派生表不产生额外费用,查询是等价的。


更新。功能split_part()更好地适合您的查询:

select split_part(post_id, '_', 2) as post_id 
from abc 
where split_part(post_id, '_', 2) = any('{912876412107255, 912883258773237}'); 

作为一个快速的注意,这里的问题是,你有相同的字段内连载两个值。这不好。如果你这样做,那是因为这些值是不同的。

你应该做的是将它们分开,或者如果它们是列表,则将它们存储为数组。现在

ALTER TABLE abc 
    ALTER COLUMN post_Id 
    SET DATA TYPE numeric[] USING (string_to_array(post_Id, '_')::numeric[]); 

,您可以FOO直接查询是否有这些领域都是平等的

SELECT * FROM abc 
WHERE post_id @> ARRAY[912876412107255::numeric]; 

或者,如果他们中的一个,为什么您使用的列别名是

SELECT * FROM abc 
WHERE post_id[2] = 912876412107255::numeric;