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

发布于 2024-12-09 09:25:06 字数 791 浏览 0 评论 0原文

使用 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);

因此,您可以看到我正在尝试测试数组内复合类型的值。

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

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

Using PostgreSQL 9.0

I have the following table setup

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]);

Now, i want to be able to write a select statement that can search and compare values of my composite types inside my mperson array column.

Example:

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

However when trying to execute this query i get the following error:

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);

So, you can see i'm trying to test the values of the composite type inside my array.

I know, i'm not supposed to use arrays and composites in my tables, but this best suites our applications requirements.

Also, we have several nested composite arrays, so a generic solution that would allow me to search many levels would be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

金橙橙 2024-12-16 09:25:06

临时测试设置:

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() 函数,在 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
   );
  • 你可以在没有主键的情况下做到这一点,但那是愚蠢的。

Temporary test setup:

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.)"}');

Call (almost the solution):

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

Returns:

 age | last_name | first_name |     address
-----+-----------+------------+-----------------
  43 | Stack     | Over       | 1234 Test Blvd.
  44 | John      | Smith      | 1234 Test Blvd.
  • key is the unnest() function, that's available in 9.0.
  • Your mistake in the example is that you forget about the ARRAY layer in between. unnest() returns one row per base element, then you can access the columns in the complex type as demonstrated.

Brave new world

IF you actually want a whole people instead of an individual that fits the criteria, I propose you add a primary key to the table and proceed as follows:

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;

Find individuals:

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

Find whole people (solution):

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
   );
  • You can do it without a primary key, but that would be foolish.
就此别过 2024-12-16 09:25:06

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

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

当然,如果此数组中有多个值,那么这是行不通的,但您也无法以其他方式获取确切的数组元素。

为什么你需要数组?您可以在每行只写入一个 person 类型的元素。

另请检查优秀的 HStore 模块,它可能更适合您的一般需求。

The construction ANY in your case looks redundant. You can write the query that way:

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

Of course, if you have multiple values in this array, that won't work, but you can't get the exact array element the other way neither.

Why do you need arrays at all? You can just write one element of type person per row.

Check also the excellent HStore module, which might better suit your generic needs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文