2015-04-01 5 views
1

У меня есть продолжение к this question, в котором я сгенерировал массивы этого типа таблицы:Создание уникальных комбинаций в Postgres размером два из массива

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

В котором в результате возвращается строка хотел бы что-то вроде этого (были в основном функциональных кнопок объединить в один список):

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] 

Я не уверен, что лучший способ идти об этом есть, но я открыт для предложений.

EDIT: Я нахожусь в 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) 
+0

Два вызова 'array_agg()' в одном и том же списке SELECT принимают элементы в том же порядке, если не указано иначе с 'ORDER BY', добавленным к параметрам функции. Таким образом, вы можете * указать, какие элементы двух массивов идут вместе, и ваша текущая функция должна выполнять эту работу. Что мне не хватает? –

+1

Как правило, такой вопрос требует, чтобы вы указали определение таблицы ('\ d mytable' в psql) и вашу версию Postgres. –

+1

Это * много * лучше скопировать/вставить то, что вы получаете от '\ d mytable' в psql. Иначе мы не можем быть уверены в полной картине. Например, я до сих пор не знаю, определены ли ваши столбцы 'NOT NULL'. –

ответ

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

Что у вас есть делает то, что вы просите: порядок элементов соответствует в обоих массивах.

Ваша первая мысль:

С 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.

+0

Я добавил некоторую информацию - единственное ограничение между всеми тремя столбцами.В моем определении возможно дублирование (val, fkey). –

Смежные вопросы