在复合类型数组中搜索元素

Posted

技术标签:

【中文标题】在复合类型数组中搜索元素【英文标题】:Search for element in array of composite types 【发布时间】:2011-10-10 20:25:15 【问题描述】:

使用 PostgreSQL 9.0

我有下表设置

CREATE TABLE person (age integer, last_name text, first_name text, address text);

CREATE TABLE my_people (mperson person[]);

INSERT INTO my_people VALUES(array[ROW(44, 'John', 'Smith', '1234 Test Blvd.')::person]);

现在,我希望能够编写一个 select 语句,它可以在我的 mperson 数组列中搜索和比较我的复合类型的值。

例子:

SELECT * FROM my_people WHERE 20 > ANY( (mperson) .age);

但是,当尝试执行此查询时,我收到以下错误:

ERROR:  column notation .age applied to type person[], which is not a composite type
LINE 1: SELECT mperson FROM my_people WHERE 20 > ANY((mperson).age);

所以,你可以看到我正在尝试测试我的数组中复合类型的值。

我知道,我不应该在我的表中使用数组和组合,但这最适合我们的应用程序要求。

此外,我们有几个嵌套的复合数组,因此我们将不胜感激有一个通用的解决方案可以让我搜索多个级别。

【问题讨论】:

我在设置中修复了INSERT 【参考方案1】:

在您的情况下,构造 ANY 看起来是多余的。你可以这样写查询:

SELECT * FROM my_people WHERE (mperson[1]).age < 20;

当然,如果你在这个数组中有多个值,那是行不通的,但是你也不能用另一种方式得到确切的数组元素。

为什么需要数组?每行只能写一个 person 类型的元素。

还可以查看出色的 HStore 模块,它可能更适合您的一般需求。

【讨论】:

【参考方案2】:

临时测试设置:

CREATE TEMP TABLE person (age integer, last_name text, first_name text
                                                     , address text);
CREATE TEMP TABLE my_people (mperson person[]);

-- test-data, demonstrating 3 different syntax styles:
INSERT INTO my_better_people (mperson)
VALUES
   (array[(43, 'Stack', 'Over', '1234 Test Blvd.')::person])

  ,(array['(44,John,Smith,1234 Test Blvd.)'::person,
          '(21,Maria,Smith,1234 Test Blvd.)'::person])

  ,('"(33,John,Miller,12 Test Blvd.)",
      "(22,Frank,Miller,12 Test Blvd.)",
      "(11,Bodi,Miller,12 Test Blvd.)"');

调用(几乎解决了):

SELECT (p).*
FROM   (
   SELECT unnest(mperson) AS p
   FROM   my_people) x
WHERE  (p).age > 33;

返回:

 age | last_name | first_name |     address
-----+-----------+------------+-----------------
  43 | Stack     | Over       | 1234 Test Blvd.
  44 | John      | Smith      | 1234 Test Blvd.
键是unnest() function, that's available in 9.0。 您在示例中的错误是您忘记了中间的 ARRAY 层。 unnest() 每个基本元素返回一行,然后您可以访问复杂类型中的列,如图所示。

美丽新世界

如果你真的想要一个完整的人而不是一个符合条件的个人,我建议你在表中添加一个主键并按照以下步骤进行:

CREATE TEMP TABLE my_better_people (id serial, mperson person[]);

-- shortcut to populate the new world by emigration from the old world ;)
INSERT INTO my_better_people (mperson)
SELECT mperson FROM my_people;

寻找个人:

SELECT id, (p).*
FROM  (
   SELECT id, unnest(mperson) AS p
   FROM   my_better_people) x
WHERE  (p).age > 20;

寻找完整的人(解决方案):

SELECT *
FROM   my_better_people p
WHERE  EXISTS (
   SELECT 1 
   FROM (
      SELECT id, unnest(mperson) AS p
      FROM   my_better_people
      ) x
   WHERE  (p).age > 20
   AND    x.id = p.id
   );
您可以在没有主键的情况下执行此操作,但这很愚蠢。

【讨论】:

以上是关于在复合类型数组中搜索元素的主要内容,如果未能解决你的问题,请参考以下文章

4复合类型

Golang复合类型

Golang学习笔记-复合类型

Golang学习笔记-复合类型

Go语言中复合的数据类型

21天从Java转向Go之第五天——水滴石穿(复合数据类型)