Problem
ich eine PostgreSQL 9.6 Datenbank mit einer Tabelle haben die gemäß einem EAV-Modell mit verschiedenen Arten von Werten. Ein Beispiel Auszug sieht wie folgt aus:PostgreSQL Kreuztabellen- mit dynamischen Spaltennamen und mehrere Eingabespalten
name |arrivalTime | boolValue | intValue | floatValue | stringValue
------+------------+-----------+----------+------------+------------
a1 | 10:00:00 | true | | |
c3 | 10:00:00 | | 12 | |
d4 | 10:00:00 | | | | hello
e5 | 15:00:00 | | | 45.67 |
c3 | 15:00:00 | | 45 | |
b2 | 20:00:00 | | | 4.567 |
a1 | 20:00:00 | false | | |
d4 | 22:00:00 | | | | bye
b2 | 22:00:00 | | | 12.34 |
Leere Zellen null
Werte in der Datenbank repräsentieren.
Jetzt möchte ich eine Pivot-Tabelle erhalten, waren die neuen Spalten die arrivalTime
und der Inhalt name
. Für das Beispiel von oben es sollte wie folgt aussehen:
arrivalTime | a1 | b2 | c3 | d4 | e5
------------+-------+-------+-------+-------+-------
10:00:00 | true | | 12 | hello |
15:00:00 | | | 45 | | 45.67
20:00:00 | false | 4.567 | | |
22:00:00 | | 12.34 | | bye |
Als Eingang zur Abfrage zum Abrufen dieses Ergebnisses erhalte ich ein Muster, welches die name
s passend und eine Start- und Endzeit den Bereich des arrivalTime
angeben.
Eigenschaften der ursprünglichen Tabelle:
- Die Einträge in der Namensspalte sind flüchtig, das heißt neue Namen kommen in und alte Namen regelmäßig verschwinden.
- Jede Kombination von
name
undarrivalTime
ist einzigartig. - Jede
name
undarrivalTime
Kombination hat genau einen Eintrag in einer der Wertspalten.
Ideen
Ich habe es schon einige Überlegungen:
- ich so viel dachte, dass die
crosstab
Funktion - Da die Spalten dynamisch sind, zwei Abfragen benötigt werden, verwendet werden sollte, wie in Dynamically generate columns in PostgreSQL oder Execute a dynamic crosstab query erläutert.
- Verwenden Sie die
format()
-Funktion zum Generieren der ersten Abfrage ist wahrscheinlich eine gute Idee.
Beispiel Tabelle
Hier ist die SQL-Code der Beispieltabelle zu erstellen:
CREATE TABLE IF NOT EXISTS playTable (
name TEXT NOT NULL,
arrivalTime TIME NOT NULL,
floatValue REAL NULL,
intValue INT NULL,
boolValue BOOLEAN NULL,
stringValue TEXT NULL,
PRIMARY KEY (name, arrivalTime),
CONSTRAINT single_value CHECK(
(boolValue IS NOT NULL)::INT +
(intValue IS NOT NULL)::INT +
(floatValue IS NOT NULL)::INT +
(stringValue IS NOT NULL)::INT = 1
)
);
Und die Werte einfügen:
INSERT INTO playTable (name, arrivalTime, boolValue) VALUES ('a1', '10:00:00', true);
INSERT INTO playTable (name, arrivalTime, intValue) VALUES ('c3', '10:00:00', 12);
INSERT INTO playTable (name, arrivalTime, stringValue) VALUES ('d4', '10:00:00', 'hello');
INSERT INTO playTable (name, arrivalTime, floatValue) VALUES ('e5', '15:00:00', 45.67);
INSERT INTO playTable (name, arrivalTime, intValue) VALUES ('c3', '15:00:00', 45);
INSERT INTO playTable (name, arrivalTime, floatValue) VALUES ('b2', '20:00:00', 4.567);
INSERT INTO playTable (name, arrivalTime, boolValue) VALUES ('a1', '20:00:00', false);
INSERT INTO playTable (name, arrivalTime, stringValue) VALUES ('d4', '22:00:00', 'bye');
INSERT INTO playTable (name, arrivalTime, floatValue) VALUES ('b2', '22:00:00', 12.34);
Pivot-Tabelle, nicht dynamische
klin Provid Ed den Ausgangspunkt der Lösung, ich denke:
Was fehlt von dieser Lösung ist der dynamische Aspekt. Als Eingabe wird ein LIKE
Muster für name
geliefert und der Bereich (d. H. Min- und Max-Wert) von arrivalTime
. Dies macht das Argument von as ct(...)
dynamisch.
Ich spielte mit der Lösung herum und erweiterte meine Frage ein wenig. Ich habe Ihren Code von 'coalesce' in' concat' geändert. Dies funktioniert gut und wichtige Hürden sind genommen, aber ich bin noch nicht im Ziel: Noch fehlt die Möglichkeit, in das Muster unter Angabe der 'name' und der' arrivalTime' Bereich. Dies macht das Argument von 'as ct (...)' dynamisch. – user711270
user711270 Sie benötigen irgendeine Art von Programmiersprache, die SQL-Abfragen für Sie generiert, wobei auf Eingabemuster geachtet wird. Wenn Sie SQL verwenden, verwenden Sie nur plpgsql, um solche dynamischen Abfragen zu erstellen. –