【问题标题】:Exclude matched array elements排除匹配的数组元素
【发布时间】:2016-01-15 21:14:44
【问题描述】:

如何从另一个数组中排除匹配的元素?

Postgres 代码:

a1 := '{1, 2, 5, 15}'::int[];
a2 := '{1, 2, 3, 6, 7, 9, 15}'::int[];

a3 := a2 ??magic_operator?? a1;

a3 中,我期望正好是 '{3, 6, 7, 9}'

最终结果

我和 lad2025 的解决方案运行良好。

array_position() 的解决方案需要 PostgreSQL 9.5 及更高版本,执行速度更快。

【问题讨论】:

  • 这些数组中的元素是否总是像您的示例中那样排序?
  • 我可以这样排序,没问题
  • [1,2,3] 和 [3,1,2] 的结果会是?你的问题不清楚。匹配的元素意味着它存在于两个数组中还是什么?
  • 是的,左右两边混淆了。我的意思是,如果两者都匹配 - 从输出中排除。右侧,5 个不匹配 - 跳过。左侧不匹配 - 输出。

标签: sql arrays postgresql


【解决方案1】:

在数组之间看起来像XOR

WITH set1 AS
(
 SELECT * FROM unnest('{1, 2, 5, 15}'::int[])
), set2 AS
(
 SELECT * FROM unnest('{1, 2, 3, 6, 7, 9, 15}'::int[])
), xor AS
(
  (SELECT * FROM set1
   UNION 
   SELECT * FROM set2)
  EXCEPT
  (SELECT * FROM set1
   INTERSECT 
   SELECT * FROM set2)
)
SELECT array_agg(unnest ORDER BY unnest)
FROM xor

输出:

"{3,5,6,7,9}"

它是如何工作的:

  1. 取消嵌套两个数组
  2. 计算总和
  3. 计算相交
  4. 从 SUM - INTERSECT
  5. 组合成数组

或者,您可以使用两个减(除)操作的总和:

(A+B) - (A^B)
<=>
(A-B) + (B-A)

利用FULL JOIN:

WITH set1 AS
(
 SELECT *
FROM unnest('{1, 2, 5, 15}'::int[])
), set2 AS
(
 SELECT *
 FROM unnest('{1, 2, 3, 6, 7, 9, 15}'::int[])
)
SELECT array_agg(COALESCE(s1.unnest, s2.unnest) 
                 ORDER BY COALESCE(s1.unnest, s2.unnest))
FROM set1 s1
FULL JOIN set2 s2
  ON s1.unnest = s2.unnest
WHERE s1.unnest IS NULL
  OR s2.unnest IS NULL;

编辑:

如果您只想要第二个数组中不是的元素,请首先使用简单的EXCEPT

SELECT array_agg(unnest ORDER BY unnest)
FROM (SELECT * FROM unnest('{1, 2, 3, 6, 7, 9, 15}'::int[])
      EXCEPT
      SELECT * FROM unnest('{1, 2, 5, 15}'::int[])) AS sub

输出:

"{3,6,7,9}"

【讨论】:

  • 条件:准确输出'{3,6,7,9}'
  • 您对匹配元素的定义很奇怪。对于匹配的元素,我假设它存在于两个表中。
  • 问题似乎是关于减法,而不是关于XOR
  • @ErwinBrandstetter 一开始不太清楚,这就是为什么我提出了“异或”解决方案。
【解决方案2】:

附加模块intarray 为整数数组提供了一个简单快速的subtraction operator -,正是您正在寻找的magic_operator

test=# SELECT '{1, 2, 3, 6, 7, 9, 15}'::int[] - '{1, 2, 5, 15}'::int[] AS result;
 ?column?
-----------
 {3,6,7,9}

您需要为每个数据库安装一次模块:

CREATE EXTENSION intarray;

它还为索引提供了特殊的运算符类:

注意only works for:

...无空的整数数组。

【讨论】:

【解决方案3】:

找了个小相似的case,修改一下。

那个 SQL 解决了我的问题。

with elements (element) as (
   select unnest(ARRAY[1, 2, 3, 6, 7, 9, 15])
)
select array_agg(element)
from elements
where array_position(ARRAY[1, 2, 5, 15],element) is null

需要 PostgreSQL 9.5 及更高版本。

【讨论】:

    猜你喜欢
    • 2019-01-05
    • 1970-01-01
    • 2012-03-21
    • 2023-03-05
    • 2014-02-23
    • 1970-01-01
    • 1970-01-01
    • 2014-05-19
    • 2021-01-28
    相关资源
    最近更新 更多