Ist es möglich, in Postgres eine Art Gruppierungskette zu erstellen? Angenommen, ich habe die folgende Tabelle:
CREATE TABLE foo AS
SELECT row_number() OVER () AS id, *
FROM ( VALUES
( 'X', 'D', 'G', 'P' ),
( 'F', 'D', 'L', 'M' ),
( 'X', 'N', 'R', 'S' ),
( 'Y', 'I', 'W', NULL ),
( 'U', 'Z', 'E', NULL )
) AS f(a,b,c,d);
id | a | b | c | d
------------------
1 | X | D | G | P
2 | F | D | L | M
3 | X | N | R | S
4 | Y | I | W |
5 | U | Z | E |
Ich möchte irgendwie eine herstellen GROUP BY
, die drei Gruppen ergibt:
1
,2
Und3
zusammen1
und2
wegen einer gemeinsamenD
in derb
Spalte1
und3
wegen einer gemeinsamenX
in dera
Spalte
4
allein (keine gemeinsamen Werte in einer der Spalten; Nullen sollten nicht übereinstimmen)5
allein (keine gemeinsamen Werte in einer der Spalten; Nullen sollten nicht übereinstimmen)
Ich verwende derzeit Postgres 9.5, aber wir werden irgendwann auf 9.6 aktualisieren. Wenn also etwas drin ist, das mir hilft, bin ich offen dafür, es zu hören.
Mit anderen Worten, ich suche nach etwas wie (sagen wir, ich habe array_agg(DISTINCT a)
usw. verwendet , um die Anzeige einfacher zu halten):
ids | as | bs | cs | ds
-----------------------------------------------------------------------
{1, 2, 3} | {'X', 'F'} | {'D', 'N'} | {'G', 'L', 'R'} | {'P', 'M', 'S'}
{4} | {'Y'} | {'I'} | {'W'} | {NULL}
{5} | {'U'} | {'Z'} | {'E'} | {NULL}
(Ich bin mir nicht ganz sicher, wie die Nullen angezeigt werden sollen. Lassen Sie sich also nicht zu sehr darauf ein. Der wichtige Punkt ist, dass sie nicht zueinander passen sollten.)
Wenn ich benutze GROUP BY CUBE (a, b, c, d)
, bekomme ich weit mehr als drei Ergebnisse ... dito GROUP BY ROLLUP
und GROUP BY GROUPING SETS
.
Gibt es einen eleganten Weg in Postgres? Ich kann mir vorstellen, wie Sie es in Ruby über Active Record machen würden (durchlaufen Sie jeden Datensatz, gruppieren Sie ihn mit vorherigen gruppierten Sätzen, die übereinstimmen), aber ich würde dies gerne in Postgres behalten, wenn dies möglich ist.
quelle
Antworten:
Angenommen, Sie suchen nach einer allgemeinen Lösung, dann gibt es meiner Meinung nach keine nicht rekursive Methode zur Lösung Ihres Problems. Wenn Ihr reales Problem mit einer großen Anzahl von Zeilen arbeiten muss, muss Ihre Arbeit möglicherweise unterbrochen werden, um eine Lösung zu erhalten, die gut genug skaliert.
Testschema und Daten:
Lösung:
Aufräumen:
quelle
arr_agg
braucht es eineDISTINCT
, die fantastisch ist.Eine andere rekursive Lösung, die:
Anfangsdaten (kopiert von Jack Douglas 'Lösung ):
Die Abfrage:
Aufräumen:
quelle