从数组生成大小为 2 的 postgres 中的唯一组合

Generating unique combinations in postgres of size two from an array

我有一个 的跟进,其中我生成了这种类型的数组 table:

 val | fkey | num
 ------------------
 1   |  1   | 10
 1   |  2   | 9  
 1   |  3   | 8  
 2   |  3   | 1 

其中生成的 returned 行会像这样(fkeys 基本上聚合到一个列表中):

1 | [1,2,3]

我想做的是根据 'num' 列中的值修改查询。也就是说,我想要这样的东西:

1 | [1,2] | [10, 9]
1 | [1,3] | [10, 8]
1 | [2,3] | [9, 8]

return 查询中第三列的排序不影响我。现在我有这样的东西:

SELECT val, array_agg(fkey), array_agg(num)
FROM mytable
GROUP BY val
Having Count(fkey) > 1

但是 return 更像是:

1 | [1,2,3] | [10, 9, 8]

这没问题,除了我无法轻易分辨出第三个数组中的哪个数字来自哪个 fkey(如果这有意义的话)。像这样的东西可以用来跟踪它:

1 | [1,2,3] | [10 - 1, 9 - 2, 8 - 3]

我不确定执行此操作的最佳方法是什么,但我愿意接受建议。

编辑:我使用的是 Postgres 9.3.6。 table 定义为:

awesome-db=# \d mytable
Table "public.mytable"
Column    |  Type   | Modifiers 
----------+---------+-----------
 val      | bytea   | not null
 fkey     | uuid    | not null
 num      | integer | not null
 Indexes:
"comp_key" UNIQUE CONSTRAINT, btree (fkey, num, val)
"fingerprint_index" btree (val)

你需要 self join 使用 row_number:

select t1.val,t1.fkey||','||t2.fkey,t1.num||','|| t2.num
from (select row_number() over(order by val) rn,
       val,
       fkey,
       num
from mytable) t1 
join (select row_number() over(order by val) rn,
       val,
       fkey,
       num
from mytable) t2
on t1.val=t2.val and t1.rn<t2.rn

SQLFIDDLE DEMO

你所拥有的满足你的要求:元素的顺序在两个数组中都对应。

你的第一个想法:

对所有列的组合 (val, fkey, num)NOT NULL 约束使用 UNIQUE 约束,您将获得两个元素的数组(首先是较小的 (num, fkey)),如下所示:

SELECT t1.val
     , ARRAY[t1.num, t2.num] AS nums
     , ARRAY[t1.fkey, t2.fkey] AS fkeys
FROM   mytable t1 
JOIN   mytable t2 USING (val)
WHERE  (t1.num, t1.fkey) < (t2.num, t2.fkey);

或者你的第二个想法:

SELECT val, array_agg(num) AS nums, array_agg(num::text || ' - ' || fkey) AS fkeys
FROM   (
   SELECT *
   FROM   mytable
   ORDER  BY num, fkey
   ) sub
GROUP  BY val
HAVING count(*) > 1;

SQL Fiddle.