当前位置: 首页 > 面试题库 >

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

井嘉胜
2023-03-14
问题内容

我有一个表,在两个单独的列中包含成对的单词。单词的顺序通常很重要,但是有时我只是想根据两个单词进行聚合,而与顺序无关。是否有一种简单的方法将具有相同单词但具有不同顺序(一行与另一行相反)的两行视为相同的“集合”?换句话说,请对待:

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[],而不是用逗号或空格分隔的文本。出于某些原因,请参见此问题。

您需要注意一些事情,例如数组之间的强制转换比其基类型之间的强制转换严格的事实。例如:

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'] = 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)

这样的列可通过GiST索引进行操作,例如数组包含或数组重叠。有关数组索引的信息,请参见PostgreSQL文档。

作为规范化的行

另一个选择是仅使用合适的键存储规范化的行。我仍然会使用array_agg它们进行排序和比较,因为SQL设置操作对此很笨拙(尤其是缺少XOR
/双面设置差异操作)。

这通常称为EAV(实体属性值)。我自己不是粉丝,但偶尔也有它的位置。除非您不使用该value组件即可使用它。

您创建一个表:

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

并为每个项目的每个set条目插入一行,而不是让每个项目都有一个数组值列。由主键强制执行的唯一约束可确保没有任何项目可以具有给定属性的重复项。属性顺序无关/不确定。

可以使用SQL集运算符(例如)进行比较,也可以EXCEPT使用它array_agg(attribute_name ORDER BY attribute_name)来形成一致排序的数组以进行比较。

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

我个人会在这种方法上使用数组。

商店

您还可以使用具有空值的hstore来存储集,因为hstore可以对重复项进行重复数据删除。9.4jsonb也可以做到这一点。

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扩展提供了有用,快速的功能,可将数组视为集合。它们仅适用于整数数组,但它们确实很有用。



 类似资料:
  • 问题内容: 如果PostgreSQL数组的所有元素均为NULL,是否有一个返回TRUE的表达式? 如果它是非NULL的值,我当然可以使用类似以下的内容: 但是我想用测试而不是测试来进行ALL操作。我不认为这是一种ALL语法,并且NULL的语义与数组混合在一起,我自己却无法想到一种实现它的形式。因此,我问堆栈溢出。;-) 我知道我可以在pl / sql或pl / pgsql中编写一个执行此操作的函数

  • 问题内容: 如果我在.NET中没有记错的话,可以为未处理的异常注册“全局”处理程序。我想知道Java是否有类似的东西。 问题答案: 是的,有,但只有在没有设置时才会触发。

  • 问题内容: 我可以找到的唯一一个是BoundedFIFOBuffer,它已被弃用。还有其他吗? 问题答案: 在Apache Commons Collections中(我假设这是您所指的)并没有被弃用,它只是移动了软件包。原来的in 已弃用,而已移至

  • 问题内容: 例如: 要么 这些名称或破折号有问题吗? 问题答案: 老实说,这取决于个人开发人员和他们自己的感受。就像您建议的那样,有两种同样好的构造CSS类的方法: 它们可以达到相同的目的,但是当您开始广泛思考时,您会发现这些样式之间的差距有多大。 分离班使他们可以重复使用: 该干的惯例是从不重复自己。通过分离or类,我们可以 重用 相同的类: 在第二种方法中-使用分隔符,代码将是: 在像这样的简

  • 本文向大家介绍python数据预处理之数据标准化的几种处理方式,包括了python数据预处理之数据标准化的几种处理方式的使用技巧和注意事项,需要的朋友参考一下 何为标准化: 在数据分析之前,我们通常需要先将数据标准化(normalization),利用标准化后的数据进行数据分析。数据标准化也就是统计数据的指数化。数据标准化处理主要包括数据同趋化处理和无量纲化处理两个方面。数据同趋化处理主要解决不同

  • 问题内容: KMeans有几个用于训练的参数,初始化模式默认为kmeans ||。问题在于它快速前进(不到10分钟)到前13个阶段,但随后 完全挂起 ,而不会产生错误! *重现问题的 *最小示例 (如果我使用1000点或随机初始化,它将成功): 如下所示,该作业不执行任何操作(该操作不会成功,失败或没有进展。)。“执行器”选项卡中没有活动/失败的任务。Stdout和Stderr Logs没有特别有