PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Holen Sie sich die JOIN-Tabelle als Array von Ergebnissen mit PostgreSQL/NodeJS

Das geht ganz einfach mit pg-promise:

function buildTree(t) {
    const v = q => t.any('SELECT id, value FROM votes WHERE question_id = $1', q.id)
        .then(votes => {
            q.votes = votes;
            return q;
        });

    return t.map('SELECT * FROM questions', undefined, v).then(a => t.batch(a));
}

db.task(buildTree)
    .then(data => {
        console.log(data); // your data tree
    })
    .catch(error => {
        console.log(error);
    });

Dasselbe wie oben, aber mit ES7 async /await Syntax:

await db.task(async t => {
    const questions = await t.any('SELECT * FROM questions');
    for(const q of questions) {
        q.votes = await t.any('SELECT id, value FROM votes WHERE question_id = $1', [q.id]);
    }
    return questions;
});
// method "task" resolves with the correct data tree

API:map, any, task, batch

Verwandte Fragen:

  • Holen Sie sich einen Eltern-Kind-Baum mit pg-promise
  • Bedingte Aufgabe mit pg-Promise

Und wenn Sie nur eine einzige Abfrage verwenden möchten, können Sie mit der Syntax von PostgreSQL 9.4 und höher Folgendes tun:

SELECT json_build_object('id', q.id, 'content', q.content, 'votes',
    (SELECT json_agg(json_build_object('id', v.id, 'value', v.value))
     FROM votes v WHERE q.id = v.question_id))
FROM questions q

Und dann wäre Ihr Pg-Promise-Beispiel:

const query =
    `SELECT json_build_object('id', q.id, 'content', q.content, 'votes',
        (SELECT json_agg(json_build_object('id', v.id, 'value', v.value))
         FROM votes v WHERE q.id = v.question_id)) json
    FROM questions q`;
    
const data = await db.map(query, [], a => a.json);

Und Sie möchten solche komplexen Abfragen auf jeden Fall in externen SQL-Dateien aufbewahren. Siehe Abfragedateien.

Schlussfolgerung

Die Wahl zwischen den beiden oben vorgestellten Ansätzen sollte auf den Leistungsanforderungen Ihrer Anwendung basieren:

  • Der Single-Query-Ansatz ist schneller, aber etwas schwierig zu lesen oder zu erweitern, da er ziemlich ausführlich ist
  • Der Ansatz mit mehreren Abfragen ist einfacher zu verstehen und zu erweitern, aber aufgrund der dynamischen Anzahl der ausgeführten Abfragen nicht besonders leistungssteigernd.

UPDATE-1

Die folgende verwandte Antwort bietet mehr Optionen, indem untergeordnete Abfragen verkettet werden, was zu einer erheblich verbesserten Leistung führt:Kombinieren Sie verschachtelte Schleifenabfragen mit dem übergeordneten Ergebnis pg-promise.

UPDATE-2

Ein weiteres Beispiel hinzugefügt, das ES7 async verwendet /await Ansatz.