2016-08-26 4 views
1

я попробовал это на следующей таблице,Получить массив записей на основе двух ключей в одной таблице

SELECT DISTINCT 
    a.main_id, 
array_agg(distinct a.secondary_id) AS arr      
FROM table1 a JOIN table1 b ON a.secondary_id = b.secondary_id or a.tertiary_id = b.tertiary_id 
group by a.main_id, a.secondary_id , b.tertiary_id 

Я добавил отчетливый опустить дубликаты Но я не могу получить всю строку в качестве элемента массив, который даже не помещает строки в массив на основе ниже упомянутого требования. Я следил за this.

Таблица сценария:

Create table table1 
( 
    id bigserial NOT NULL, 
    main_id integer NOT NULL, 
    secondary_id integer, 
    tertiary_id integer, 
    data1 text, 
    data2 text, 
    CONSTRAINT table1_pk PRIMARY KEY (main_id) 

) 

данных:

INSERT INTO table1(
      main_id, secondary_id, tertiary_id, data1, data2) 
    VALUES (1,2,NULL,'data1_1_2_N','data2_1_2_N'), 
     (2,2,NULL,'data1_2_2_N','data2_2_2_N'), 
     (3,3,5,'data1_3_3_5','data2_3_3_5'), 
     (4,3,5,'data1_4_3_5','data2_4_3_5'), 
     (5,NULL,1,'data1_5_N_1','data2_5_N_1'), 
     (6,NULL,1,'data1_6_N_1','data2_6_N_1'), 
     (7,NULL,1,'data1_7_N_1','data2_7_N_1'), 
     (8,NULL,2,'data1_8_N_2','data2_8_N_2'), 
     (9,NULL,2,'data1_9_N_2','data2_9_N_2'), 
     (10,NULL,3,'data1_10_N_3','data2_10_N_3'), 
     (11,12,12,'data1_11_12_12','data2_11_12_12'), 
     (12,12,11,'data1_12_12_11','data2_12_12_11') 

Требование:

Если secondary_id равно в двух или более рядов их следует рассматривать в качестве одного set, else, если tertiary_id такой, что его можно рассматривать как один набор.

Ожидаемый результат:

1 | {(1,2,NULL,'data1_1_2_N','data2_1_2_N'),(2,2,NULL,'data1_2_2_N','data2_2_2_N')} 
    2 | {(3,3,NULL,'data1_3_3_N','data2_3_3_N'),(4,3,NULL,'data1_4_3_N','data2_4_3_N')} 
    3 | {(5,NULL,1,'data1_5_N_1','data2_5_N_1'),(6,NULL,1,'data1_6_N_1','data2_6_N_1'),(7,NULL,1,'data1_7_N_1','data2_7_N_1')} 
    4 | {(8,NULL,2,'data1_8_N_2','data2_8_N_2'),(9,NULL,2,'data1_9_N_2','data2_9_N_2')} 
    5 | {(10,NULL,3,'data1_10_N_3','data2_10_N_3')} 
    6 | {(11,12,12,'data1_11_12_12','data2_11_12_12'),(12,12,11,'data1_12_12_11','data2_12_12_11') } 

Version "PostgreSQL 9.3.11"

+1

Удалить 'DISTINCT a.main_id,' из 'select', удалить' a.main_id, 'из' group by', изменить 'array_agg (различный a.secondary_id)' на 'array_agg (отличный a. *)' - то вы получите то, что хотите. – Abelisto

+0

@Abelisto. Ваш запрос работает отлично, за исключением одного сценария .. когда тот же идентификатор появляется как в «secondary_id», так и «tertiary_id». например: main_id 11 и 12 duplicate. Все остальные в порядке –

+0

@MarlonAbeykoon, почему у вас нет main_id 11 и 12 в ожидаемом выходе? –

ответ

1

Это должно обеспечить свой выход. Трюк привязывается к условной группе по предложению, чтобы обрабатывать случаи, когда secondary_id и tertiary_id одинаковы для записи, которая имеет соответствующую запись в обоих этих полях.

select array_agg(distinct t1) 
from table1 t1 
join table1 t2 on 
    t1.secondary_id = t2.secondary_id 
    or t1.tertiary_id = t2.tertiary_id 
group by 
    case 
    when t1.secondary_id is null or t1.secondary_id is null 
     then concat(t1.secondary_id,'#',t1.tertiary_id) -- #1 
    when t1.secondary_id is not null and t1.tertiary_id is not null and t1.secondary_id = t2.secondary_id 
     then t1.secondary_id::TEXT -- #2 
    when t1.secondary_id is not null and t1.tertiary_id is not null and t1.tertiary_id = t2.tertiary_id 
     then t1.tertiary_id::TEXT -- #3 
    end 
order by 1 

Стандартный случай, когда любое из полей является нулевым, что означает # 1. Нам нужно группировать оба столбца, и мы обманываем его, объединяя оба значения из столбцов с отметкой # и делая группу с помощью этого конкатенированного столбца.

Для # 2 и # 3 нам нужно указать значение группировки, чтобы ввести text, чтобы он прошел (типы, возвращаемые оператором CASE, должны быть одинаковыми).

Вариант №2 служит случаю, когда оба значения не являются нулевыми, а secondary_id соответствует этим «выбранным» строкам из selfjoin. Вариант № 3 аналогичен, но для tertiary_id.

Выход:

            array_agg 
------------------------------------------------------------------------------------------------------------ 
{"(1,1,2,,data1_1_2_N,data2_1_2_N)","(2,2,2,,data1_2_2_N,data2_2_2_N)"} 
{"(3,3,3,5,data1_3_3_5,data2_3_3_5)","(4,4,3,5,data1_4_3_5,data2_4_3_5)"} 
{"(5,5,,1,data1_5_N_1,data2_5_N_1)","(6,6,,1,data1_6_N_1,data2_6_N_1)","(7,7,,1,data1_7_N_1,data2_7_N_1)"} 
{"(8,8,,2,data1_8_N_2,data2_8_N_2)","(9,9,,2,data1_9_N_2,data2_9_N_2)"} 
{"(10,10,,3,data1_10_N_3,data2_10_N_3)"} 
{"(11,11,4,4,data1_11_4_4,data2_11_4_4)","(12,12,4,11,data1_12_4_11,data2_12_4_11)"} 

Если вы хотите, чтобы избавиться от колонки id из вашей записи, вы можете использовать КТР и выбрать все столбцы, но идентификатор, а затем обратиться к этому КТР в предложении.

+0

Спасибо за ответ и объяснение +1 –

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