Postgres按数组元素范围选择

时间:2017-12-06 15:55:32

标签: postgresql select

在我的表中,我有专栏facebook,我存储了facebook数据(评论数,分享数等),而且它是一个数组。例如:

{{total_count,14},{comment_count,0},{comment_plugin_count,0},{share_count,12},{reaction_count,2}}

现在我试图选择facebook total_count介于5到10之间的行。我已经尝试过了:

SELECT * FROM pl where regexp_matches(array_to_string(facebook, ' '), '(\d+).*')::numeric[] BETWEEN 5 and 10;

但是我收到了错误:

  

错误:运算符不存在:numeric []> = integer

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

无需将数组转换为文本并使用regexp。您可以访问数组的特定元素,例如:

with pl(facebook) as (
values ('{{total_count,14},{comment_count,0},{comment_plugin_count,0},{share_count,12},{reaction_count,2}}'::text[])
)

select facebook[1][2] as total_count
from pl;

 total_count 
-------------
 14
(1 row) 

您的查询可能如下所示:

select *
from pl 
where facebook[1][2]::numeric between 5 and 10

更新。如果您使用单词null而不是空字符串'''',则可以避免评论中描述的问题。

with pl(id, facebook) as (
values 
    (1, '{{total_count,14},{comment_count,0}}'::text[]),
    (2, '{{total_count,null},{comment_count,null}}'::text[]),
    (3, '{{total_count,7},{comment_count,10}}'::text[])
)

select *
from pl 
where facebook[1][2]::numeric between 5 and 10

 id |               facebook               
----+--------------------------------------
  3 | {{total_count,7},{comment_count,10}}
(1 row) 

然而,如果没有额外的评论,留下你的问题是不公平的。这个案例适合作为演讲的一个例子如何不在Postgres中使用数组。你至少有几个更好的选择。最高效和最自然的是简单地使用常规整数列:

create table pl (
    ...
    facebook_total_count integer,
    facebook_comment_count integer, 
    ...
    );

如果由于某种原因需要将此数据与表中的其他数据分开,请使用主表的外键创建一个新的辅助表。

如果由于一些神秘的原因你必须将数据存储在一个列中,请使用jsonb类型,例如:

with pl(id, facebook) as (
values 
    (1, '{"total_count": 14, "comment_count": 0}'::jsonb),
    (2, '{"total_count": null, "comment_count": null}'::jsonb),
    (3, '{"total_count": 7, "comment_count": 10}'::jsonb)
)

select *
from pl 
where (facebook->>'total_count')::integer between 5 and 10

hstore可以替代jsonb

所有这些方式都比您当前的模型更容易维护和更有效。是时候走向光明的一面了。