加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

在PostgreSQL中是否有处理无序数组(集合)的标准方法?

发布时间:2020-12-13 15:57:54 所属栏目:百科 来源:网络整理
导读:我有一个表,包含两个单独的列中的单词对.单词的顺序通常很重要,但有时候我只想基于这两个单词进行聚合,而不管顺序如何.是否有一种简单的方法来处理具有相同单词但具有不同顺序(一行与另一行相反)的两行作为相同的“集合”?换句话说,对待: apple orangeoran
我有一个表,包含两个单独的列中的单词对.单词的顺序通常很重要,但有时候我只想基于这两个单词进行聚合,而不管顺序如何.是否有一种简单的方法来处理具有相同单词但具有不同顺序(一行与另一行相反)的两行作为相同的“集合”?换句话说,对待:

apple orange
orange apple

如:

(apple,orange)
(apple,orange)

解决方法

目前还没有内置方式.

作为数组

如果在保存时始终将它们标准化,则可以将数组视为集合,始终将它们存储为已排序和重复数据删除.如果PostgreSQL有一个内置的C函数来做这件事会很棒,但事实并非如此.我看了一下写了一个,但C数组API很可怕,所以即使我写了一堆扩展,我还是小心翼翼地远离这个.

如果你不介意适度的性能,你可以在SQL中做到这一点:

CREATE OR REPLACE FUNCTION array_uniq_sort(anyarray) RETURNS anyarray AS $$
SELECT array_agg(DISTINCT f ORDER BY f) FROM unnest($1) f;
$$LANGUAGE sql IMMUTABLE;

然后将所有保存包装在对array_uniq_sort的调用中,或者使用触发器强制执行.然后,您可以比较您的数组是否相等.如果您改为在应用程序端执行排序/唯一,则可以避免对应用程序中的数据进行array_uniq_sort调用.

如果你这样做,请将你的“集合”存储为数组列,如text [],而不是逗号或空格分隔的文本.由于某些原因,请参见this question.

你需要注意一些事情,比如数组之间的强制转换比它们的基类型之间的强制转换更严格.例如.:

regress=> SELECT 'a' = 'a'::varchar,'b' = 'b'::varchar;
 ?column? | ?column? 
----------+----------
 t        | t
(1 row)

regress=> SELECT ARRAY['a','b'] = ARRAY['a','b']::varchar[];
ERROR:  operator does not exist: text[] = character varying[]
LINE 1: SELECT ARRAY['a','b']::varchar[];
                              ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
regress=> SELECT ARRAY['a','b']::varchar[] = ARRAY['a','b']::varchar[];
 ?column? 
----------
 t
(1 row)

对于像array-contains或array-overlaps这样的操作,这些列是GiST-indexable;请参阅有关数组索引的PostgreSQL文档.

作为规范化的行

另一种选择是使用合适的密钥存储规范化的行.我仍然使用array_agg进行排序和比较,因为SQL设置操作可能很笨拙(特别是考虑到缺少XOR /双面设置差异操作).

这通常称为EAV(实体属性值).我自己不是粉丝,但偶尔会有它的位置.除非您在没有价值组件的情况下使用它.

你创建一个表:

CREATE TABLE item_attributes (
    item_id integer references items(id),attribute_name text,primary key(item_id,attribute_name)
);

并为每个项目的每个集合条目插入一行,而不是让每个项目都有一个数组值列.主键强制执行的唯一约束确保没有项可能具有给定属性的重复项.属性排序无关紧要/未定义.

可以使用SQL集合运算符(如EXCEPT)或使用array_agg(attribute_name ORDER BY attribute_name)进行比较,以形成一致排序的数组以进行比较.

索引仅限于确定给定项目是否具有给定属性.

就个人而言,我会在这种方法中使用数组.

hstore

您还可以使用具有空值的hstore来存储集,因为hstore可以重复密钥. 9.4的jsonb也适用于此.

regress=# create extension hstore;
CREATE EXTENSION
regress=# SELECT hstore('a => 1,b => 1') = hstore('b => 1,a => 1,b => 1');
 ?column? 
----------
 t
(1 row)

但它只对文本类型非常有用.例如.:

regress=# SELECT hstore('"1.0" => 1,"2.0" => 1') = hstore('"1.00" => 1,"1.000" => 1,"2.0" => 1');
 ?column? 
----------
 f
(1 row)

而且我认为这很难看.所以,我再次赞成阵列.

仅适用于整数数组

intarray扩展提供了有用的快速函数,用于将数组作为集处理.它们只适用于整数数组,但它们确实非常有用.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读