2016-06-23 4 views
1

die folgenden Ausgangsdaten Gegeben:pflegen konsistente PostgreSQL Array Spaltenindizes während Array Spalten verketten, wenn sie mit leeren Spalte Umgang Werte

CREATE TABLE t1 AS 
    SELECT generate_series(1, 20) AS id, 
    (SELECT array_agg(generate_series) FROM generate_series(1, 6)) as array_1; 

CREATE TABLE t2 AS 
    SELECT generate_series(5, 10) AS id, 
    (SELECT array_agg(generate_series) FROM generate_series(7, 10)) as array_2; 

CREATE TABLE t3 AS 
    SELECT generate_series(8, 15) AS id, 
    (SELECT array_agg(generate_series) FROM generate_series(11, 15)) as array_3; 

Ich mag würde eine äußere Verknüpfung zwischen mehreren Tabellen, die jeweils mit einer festen Länge tun Array-Spalte, die innerhalb einer gegebenen Tabelle einheitlich ist, sich jedoch von Tabelle zu Tabelle (wie in den obigen Beispielen) unterscheiden kann, indem die Array-Spalten in jeder Tabelle zu einer großen Array-Spalte verkettet werden. Ich habe mich gefragt, ob es eine effiziente oder direkte Möglichkeit gibt, die konsistente Indizierung in der neuen kombinierten Spalte beizubehalten und NULL Spaltenwerte (verursacht durch den äußeren Join) durch ein Array von NULL Werten zu ersetzen, so dass die letzte Array-Spalte eine einheitliche Länge hat. Anders als im obigen Beispiel, in meinem tatsächlichen Anwendungsfall, werde ich nicht wissen, die Länge der Array-Spalte jeder Tabelle a priori, nur dass es eine einheitliche Länge in der gesamten Tabelle sein wird. Mit anderen Worten: diese Abfrage statt:

SELECT id, (array_1 || array_2 || array_3) AS combined_array FROM 
t1 LEFT OUTER JOIN t2 USING(id) LEFT OUTER JOIN t3 USING (id); 

Welche produziert:

id |   combined_array 
----+--------------------------------------- 
1 | {1,2,3,4,5,6} 
2 | {1,2,3,4,5,6} 
3 | {1,2,3,4,5,6} 
4 | {1,2,3,4,5,6} 
5 | {1,2,3,4,5,6,7,8,9,10} 
6 | {1,2,3,4,5,6,7,8,9,10} 
7 | {1,2,3,4,5,6,7,8,9,10} 
8 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} 
9 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} 
10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} 
11 | {1,2,3,4,5,6,11,12,13,14,15} 
12 | {1,2,3,4,5,6,11,12,13,14,15} 
13 | {1,2,3,4,5,6,11,12,13,14,15} 
14 | {1,2,3,4,5,6,11,12,13,14,15} 
15 | {1,2,3,4,5,6,11,12,13,14,15} 
16 | {1,2,3,4,5,6} 
17 | {1,2,3,4,5,6} 
18 | {1,2,3,4,5,6} 
19 | {1,2,3,4,5,6} 
20 | {1,2,3,4,5,6} 
(20 rows) 

würde ich mit dem Ergebnis zufrieden aussehen:

id |   combined_array 
----+--------------------------------------- 
1 | {1,2,3,4,5,6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL} 
2 | {1,2,3,4,5,6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL} 
3 | {1,2,3,4,5,6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL} 
4 | {1,2,3,4,5,6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL} 
5 | {1,2,3,4,5,6,7,8,9,10,NULL,NULL,NULL,NULL,NULL} 
6 | {1,2,3,4,5,6,7,8,9,10,NULL,NULL,NULL,NULL,NULL} 
7 | {1,2,3,4,5,6,7,8,9,10,NULL,NULL,NULL,NULL,NULL} 
8 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} 
9 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} 
10 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} 
11 | {1,2,3,4,5,6,NULL,NULL,NULL,NULL,11,12,13,14,15} 
12 | {1,2,3,4,5,6,NULL,NULL,NULL,NULL,11,12,13,14,15} 
13 | {1,2,3,4,5,6,NULL,NULL,NULL,NULL,11,12,13,14,15} 
14 | {1,2,3,4,5,6,NULL,NULL,NULL,NULL,11,12,13,14,15} 
15 | {1,2,3,4,5,6,NULL,NULL,NULL,NULL,11,12,13,14,15} 
16 | {1,2,3,4,5,6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL} 
17 | {1,2,3,4,5,6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL} 
18 | {1,2,3,4,5,6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL} 
19 | {1,2,3,4,5,6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL} 
20 | {1,2,3,4,5,6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL} 
(20 rows) 

so dass jede Zeile enthält eine Reihe von Länge 15

+0

n-Länge? Kann jede Reihe eine andere Länge haben? Nimmst du dann den größten Wert? Wenn ja, was mit kürzeren Reihen zu tun? –

+0

Sorry, meine Beschreibung ist etwas verwirrend. Jede Tabelle hat eine Array-Spalte mit einer einheitlichen Länge in der gesamten Tabelle, aber ich weiß nicht unbedingt die Länge des Arrays für eine bestimmte Tabelle a priori, wenn das sinnvoll ist. So kann Tabelle 1 eine Array-Spalte der Länge 10 und Tabelle 2 eine Array-Spalte der Länge 3 haben. In meinem Anwendungsfall kann ich diese Werte nicht fest codieren. –

Antwort

1

meine eigene Frage zu beantworten, hier ist die Abfrage, die ich kam mit, dass die Arbeit zu tun scheint. Es scheint mir nicht besonders elegant oder effizient zu sein, also offen für andere Antworten.

SELECT id, (
    coalesce(array_1, array_fill(NULL::INT, 
    ARRAY[(SELECT max(array_length(array_1, 1)) FROM t1)])) || 
    coalesce(array_2, array_fill(NULL::INT, 
    ARRAY[(SELECT max(array_length(array_2, 1)) FROM t2)])) || 
    coalesce(array_3, array_fill(NULL::INT, 
    ARRAY[(SELECT max(array_length(array_3, 1)) FROM t3)])) 
) AS combined_array FROM 
t1 LEFT OUTER JOIN t2 USING(id) LEFT OUTER JOIN t3 USING (id);