【问题标题】:Postgres - Function to return the intersection of 2 ARRAYs?Postgres - 返回两个数组的交集的函数?
【发布时间】:2017-07-28 12:57:50
【问题描述】:

在 postgresql 中,如果两个数组有共同的成员,即它们重叠,则可以使用 && 运算符返回 t (true)。是否有一个函数/运算符可以返回这些常见成员是什么?

即像这样的

select arrray_intersection(ARRAY[1, 4, 2], ARRAY[2, 3]);
ARRAY[2]

【问题讨论】:

标签: sql postgresql


【解决方案1】:

Since 8.4, there are useful builtins in Postgres 这使the function from the first answer 更容易并且可能更快(这就是 EXPLAIN 告诉我的,无论如何:“(成本=0.00..0.07 行=1 宽度=64)”对于这个查询与“(成本=0.00 ..60.02 rows=1 width=64)" 为原始的)。

简化代码为:

SELECT ARRAY
    (
        SELECT UNNEST(a1)
        INTERSECT
        SELECT UNNEST(a2)
    )
FROM  (
        SELECT  array['two', 'four', 'six'] AS a1
              , array['four', 'six', 'eight'] AS a2
      ) q;

是的,你可以把它变成一个函数:

CREATE FUNCTION array_intersect(anyarray, anyarray)
  RETURNS anyarray
  language sql
as $FUNCTION$
    SELECT ARRAY(
        SELECT UNNEST($1)
        INTERSECT
        SELECT UNNEST($2)
    );
$FUNCTION$;

你可以称之为

SELECT array_intersect(array['two', 'four', 'six']
                     , array['four', 'six', 'eight']);

但您也可以将其称为内联:

 SELECT array(select unnest(array['two', 'four', 'six']) intersect
              select unnest(array['four', 'six', 'eight']));

【讨论】:

  • 对于倒数第二个示例,我收到错误 function array_intersect(text[], text[]) does not exist。最后一个例子运行良好!
  • 我们怎样才能不区分大小写?
  • 为了帮助优化,您可以将array_intersect 函数标记为IMMUTABLE
【解决方案2】:

尝试& 而不是&&

请参阅PostgreSQL Docs 了解更多信息。

【讨论】:

【解决方案3】:

另一种方法..

SELECT ARRAY( SELECT * FROM UNNEST( $1 ) WHERE UNNEST = ANY( $2 ) );

【讨论】:

  • 这对我来说很完美,因为它保留了顺序。谢谢!
【解决方案4】:

如果您不介意安装扩展程序,intarray extension 提供了& 运算符来执行此操作,正如@dwc 指出的那样。:

SELECT ARRAY[1, 4, 2] & ARRAY[2, 3];

返回{2}

【讨论】:

  • 您使用的是哪个 postgresql 版本?在 9.6 中,我收到以下错误,我也无法在文档中找到它。还是我在这里做错了什么? ERROR: operator does not exist: integer[] & integer[] LINE 1: SELECT ARRAY[1,4,2] & ARRAY[2,3] ^ HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
  • 啊,等等,根据postgresql.org/docs/current/static/intarray.html,它是对 postgresql 的扩展。值得一提的是。
  • 请注意,这个扩展非常有名,似乎受到 Heroku、Amazon RDS 和其他可能的支持。 dwc 2009 年的一个答案是提出完全相同的 & 运算符,但它没有提供使用示例。
【解决方案5】:

你可以使用这个功能:

CREATE OR REPLACE FUNCTION intersection(anyarray, anyarray) RETURNS anyarray as $$
SELECT ARRAY(
    SELECT $1[i]
    FROM generate_series( array_lower($1, 1), array_upper($1, 1) ) i
    WHERE ARRAY[$1[i]] && $2
);
$$ language sql;

它应该适用于任何类型的数组,你可以像这样使用它:

SELECT intersection('{4,2,6}'::INT4[], '{2,3,4}'::INT4[]);

【讨论】:

    【解决方案6】:
    SELECT  ARRAY
            (
            SELECT  a1[s]
            FROM    generate_series(array_lower(a1, 1), array_upper(a1, 1)) s
            INTERSECT
            SELECT  a2[s]
            FROM    generate_series(array_lower(a2, 1), array_upper(a2, 1)) s
            )
    FROM    (
            SELECT  array['two', 'four', 'six'] AS a1, array['four', 'six', 'eight'] AS a2
            ) q
    

    也适用于非整数数组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-14
      • 2012-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多