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

Wie führe ich in psql eine Schleife für eine Auswahlabfrage mit CTEs aus und bekomme die Ausgabe angezeigt, wenn ich sie in einer schreibgeschützten Datenbank ausführe?

Wenn ich das richtig entziffere, willst du im Grunde alle Personen auswählen, bei denen die Zeilennummer nach absteigender ID in der Adresse vorkommt. Das Endergebnis sollte dann auf bestimmte dieser Zeilennummern beschränkt werden.

Dann brauchen Sie das umständliche LIMIT nicht zu verwenden /OFFSET überhaupt konstruieren. Sie können einfach die row_number() verwenden Fensterfunktion.

Um nach den Zeilennummern zu filtern, können Sie einfach IN verwenden . Je nachdem, was Sie hier wollen, können Sie entweder eine Liste von Literalen verwenden, insbesondere wenn die Zahlen nicht fortlaufend sind. Oder Sie können generate_series() verwenden um eine Liste mit fortlaufenden Nummern zu erstellen. Natürlich können Sie auch eine Unterabfrage verwenden, wenn die Zahlen in einer anderen Tabelle gespeichert sind.

Mit einer Liste von Literalen, die etwa so aussehen würden:

SELECT pn.personid,
       pn.lastname,
       pn.firstname,
       pn.address,
       pn.city
       FROM (SELECT p.personid,
                    p.lastname,
                    p.firstname,
                    p.address,
                    p.city,
                    row_number() OVER (ORDER BY p.personid DESC) n
                    FROM persons p) pn
       WHERE pn.address LIKE concat('%', pn.n, '%')
             AND pn.n IN (1, 2, 4);

Wenn Sie generate_series() verwenden möchten Ein Beispiel wäre:

SELECT pn.personid,
       pn.lastname,
       pn.firstname,
       pn.address,
       pn.city
       FROM (SELECT p.personid,
                    p.lastname,
                    p.firstname,
                    p.address,
                    p.city,
                    row_number() OVER (ORDER BY p.personid DESC) n
                    FROM persons p) pn
       WHERE pn.address LIKE concat('%', pn.n, '%')
             AND pn.n IN (SELECT s.n
                                 FROM generate_series(1, 3) s (n));
                             

Und eine Unterabfrage einer anderen Tabelle könnte so verwendet werden:

SELECT pn.personid,
       pn.lastname,
       pn.firstname,
       pn.address,
       pn.city
       FROM (SELECT p.personid,
                    p.lastname,
                    p.firstname,
                    p.address,
                    p.city,
                    row_number() OVER (ORDER BY p.personid DESC) n
                    FROM persons p) pn
       WHERE pn.address LIKE concat('%', pn.n, '%')
             AND pn.n IN (SELECT t.nmuloc
                                 FROM elbat t);

Für größere Zahlenmengen können Sie auch einen INNER JOIN verwenden auf die Zahlen statt IN .

Verwenden von generate_series() :

SELECT pn.personid,
       pn.lastname,
       pn.firstname,
       pn.address,
       pn.city
       FROM (SELECT p.personid,
                    p.lastname,
                    p.firstname,
                    p.address,
                    p.city,
                    row_number() OVER (ORDER BY p.personid DESC) n
                    FROM persons p) pn
            INNER JOIN generate_series(1, 1000000) s (n)
                       ON s.n = pn.n
       WHERE pn.address LIKE concat('%', pn.n, '%');

Oder wenn sich die Zahlen in einer anderen Tabelle befinden:

SELECT pn.personid,
       pn.lastname,
       pn.firstname,
       pn.address,
       pn.city
       FROM (SELECT p.personid,
                    p.lastname,
                    p.firstname,
                    p.address,
                    p.city,
                    row_number() OVER (ORDER BY p.personid DESC) n
                    FROM persons p) pn
            INNER JOIN elbat t
                       ON t.nmuloc = pn.n
       WHERE pn.address LIKE concat('%', pn.n, '%');

Beachten Sie, dass ich auch den Musterabgleich für reguläre Ausdrücke in ein einfaches LIKE geändert habe . Das würde die Abfragen etwas portabler machen. Aber Sie können das natürlich durch jeden Ausdruck ersetzen, den Sie wirklich brauchen.

db<>fiddle (mit einigen Varianten)