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

时间:2015-04-01 05:09:37

标签: sql arrays postgresql aggregate-functions

我有this question的后续跟踪,我在其中生成了这种类型的表的数组:

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

结果返回的行会像这样(fkeys基本上聚合到一个列表):

1 | [1,2,3]

我想要做的是修改查询,分别与' num'中的值相对应。柱。也就是说,我想要像:

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

回复查询中第三列的排序并不会让我烦恼。现在我有这样的事情:

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

但是这会更像是:

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

哪个没关系,除了我不能轻易分辨出第三个数组中的哪个数字来自什么fkey(如果有意义的话)。像这样的东西可以跟踪它:

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

我不确定这样做的最佳方式是什么,但我愿意接受建议。

编辑:我在Postgres 9.3.6上。表定义是:

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)

2 个答案:

答案 0 :(得分:1)

您需要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

答案 1 :(得分:1)

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

你的第一个想法:

对所有列的UNIQUE(val, fkey, num)组合约束NOT NULL约束,您将得到两个元素的数组(首先是较小的(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.