it-swarm.com.de

Liefert den letzten Datensatz einer Tabelle in Postgres

Ich verwende Postgres und kann den letzten Datensatz meiner Tabelle nicht abrufen:

 my_query = client.query("SELECT timestamp,value,card from my_table");

Wie kann ich wissen, dass der Zeitstempel eine eindeutige Kennung des Datensatzes ist?

27
Luc

Wenn unter "letzter Datensatz" Sie den Datensatz angeben, der den neuesten Zeitstempelwert hat, versuchen Sie Folgendes:

my_query = client.query("
  SELECT TIMESTAMP,
    value,
    card
  FROM my_table
  ORDER BY TIMESTAMP DESC
  LIMIT 1
");
62
bpgergo

sie können verwenden

SELECT timestamp, value, card 
FROM my_table 
ORDER BY timestamp DESC 
LIMIT 1

vorausgesetzt, Sie möchten auch nach timestamp sortieren?

14
chl

Wenn Sie einen Tipp akzeptieren, erstellen Sie in dieser Tabelle eine ID wie "Seriell". Der Standardwert dieses Feldes lautet:

nextval('table_name_field_seq'::regclass).

Sie verwenden also eine Abfrage, um das letzte Register aufzurufen. An deinem Beispiel:

pg_query($connection, "SELECT currval('table_name_field_seq') AS id;

Ich hoffe dieser Tipp hilft dir.

6
phsaires

Der letzte eingefügte Datensatz kann mit diesem Befehl abgefragt werden, vorausgesetzt, Sie haben die "id" als Primärschlüssel:

SELECT timestamp,value,card FROM my_table WHERE id=(select max(id) from my_table)

Angenommen, jede neu eingefügte Zeile verwendet den höchsten ganzzahligen Wert für die ID der Tabelle.

4
Allan Registos

Einfacher Weg: ORDER BY in Verbindung mit LIMIT

SELECT timestamp, value, card
FROM my_table
ORDER BY timestamp DESC
LIMIT 1;

LIMIT ist jedoch kein Standard und wird von Wikipedia , angegeben. Die Kernfunktionalität des SQL-Standards definiert nicht explizit eine Standardsortierreihenfolge für Nullen.. Schließlich wird nur eine Zeile zurückgegeben, wenn sich mehrere Datensätze den maximalen Zeitstempel teilen.

Beziehungsweg:

In der Regel wird dazu überprüft, dass keine Zeile einen höheren Zeitstempel hat als jede Zeile, die wir abrufen.

SELECT timestamp, value, card
FROM my_table t1
WHERE NOT EXISTS (
  SELECT *
  FROM my_table t2
  WHERE t2.timestamp > t1.timestamp
);

Es ist meine Lieblingslösung und die, die ich normalerweise benutze. Der Nachteil ist, dass unsere Absicht nicht sofort klar ist, wenn Sie einen Blick auf diese Abfrage werfen.

Lehrweise: MAX

Um dies zu umgehen, kann man MAX in der Unterabfrage anstelle der Korrelation verwenden.

SELECT timestamp, value, card
FROM my_table
WHERE timestamp = (
  SELECT MAX(timestamp)
  FROM my_table
);

Ohne einen Index sind jedoch zwei Durchgänge erforderlich, während die vorherige Abfrage die Lösung mit nur einem Scan finden kann. Allerdings sollten wir bei der Gestaltung von Abfragen nicht die Leistung berücksichtigen, es sei denn, dies ist erforderlich, da Optimierer mit der Zeit eine Verbesserung erwarten können. Diese spezielle Art von Abfrage wird jedoch durchaus verwendet.

Show off way: Windowing-Funktionen

Ich empfehle das nicht, aber vielleicht können Sie einen guten Eindruck bei Ihrem Chef oder so machen ;-)

SELECT DISTINCT
  first_value(timestamp) OVER w,
  first_value(value) OVER w,
  first_value(card) OVER w
FROM my_table
WINDOW w AS (ORDER BY timestamp DESC);

Tatsächlich hat dies den Vorteil, zu zeigen, dass eine einfache Abfrage auf vielfältige Weise ausgedrückt werden kann (es gibt mehrere andere, die ich mir vorstellen kann), und dass die Auswahl der einen oder der anderen Form nach mehreren Kriterien erfolgen sollte, z.

  • portabilität (relationale/instruktive Wege)
  • effizienz (relationaler Weg)
  • ausdruckskraft (einfache/lehrreiche Art)
2
Fabian Pijcke

Um die letzte Reihe zu bekommen,

Letzte Zeile in der sortierten Reihenfolge abrufen : Falls die Tabelle eine Spalte enthält, die Zeit/Primärschlüssel angibt,

  1. Verwendung der LIMIT -Klausel

SELECT * FROM USERS ORDER BY CREATED_TIME DESC LIMIT 1;

  1. Verwenden der FETCH -Klausel - Referenz

SELECT * FROM USERS ORDER BY CREATED_TIME FETCH FIRST ROW ONLY;

Letzte Zeile in der Reihenfolge des Einfügens der Zeilen abrufen : Falls die Tabelle keine Spalten enthält, in denen die Zeit/eindeutige Bezeichner angegeben sind

  1. Verwenden der Systemspalte CTID, wobei ctid die physische Position der Zeile in einer Tabelle darstellt - Referenz

    SELECT * FROM USERS WHERE CTID = (SELECT MAX(CTID) FROM USERS);

Betrachten Sie die folgende Tabelle,

userid |username |    createdtime |
     1 |       A |  1535012279455 |
     2 |       B |  1535042279423 | //as per created time, this is the last row
     3 |       C |  1535012279443 |
     4 |       D |  1535012212311 |
     5 |       E |  1535012254634 | //as per insertion order, this is the last row

Die Abfrage 1 und 2 gibt Folgendes zurück:

userid |username |    createdtime |
     2 |       B |  1535042279423 |

während 3 zurückkehrt,

userid |username |    createdtime |
     5 |       E |  1535012254634 |

Hinweis : Beim Aktualisieren einer alten Zeile wird die alte Zeile entfernt und die Daten aktualisiert und als neue Zeile in die Tabelle eingefügt. Wenn Sie also die folgende Abfrage verwenden, wird das Tupel zurückgegeben, auf dem die Datenänderung spätestens erfolgt.

Aktualisieren Sie nun eine Zeile mit

UPDATE USERS SET USERNAME = 'Z' WHERE USERID='3'

der tisch wird wie,

userid |username |    createdtime |
     1 |       A |  1535012279455 |
     2 |       B |  1535042279423 |
     4 |       D |  1535012212311 |
     5 |       E |  1535012254634 |
     3 |       Z |  1535012279443 |

Nun gibt die Abfrage 3 zurück,

userid |username |    createdtime |
     3 |       Z |  1535012279443 |
0
Vignesh Raja

Dies sind alles gute Antworten, aber wenn Sie möchten, dass eine Aggregatfunktion dies tut, um die letzte Zeile in der Ergebnismenge zu übernehmen, die von einer beliebigen Abfrage generiert wurde, ist es gibt eine Standardmethode, dies zu tun } (aus dem Postgres-Wiki, sollte jedoch in einem beliebigen Fall funktionieren, der vor einem Jahrzehnt oder mehr dem SQL-Standard angemessen war):

-- Create a function that always returns the last non-NULL item
CREATE OR REPLACE FUNCTION public.last_agg ( anyelement, anyelement )
RETURNS anyelement LANGUAGE SQL IMMUTABLE STRICT AS $$
        SELECT $2;
$$;

-- And then wrap an aggregate around it
CREATE AGGREGATE public.LAST (
        sfunc    = public.last_agg,
        basetype = anyelement,
        stype    = anyelement
);

select ... limit 1 ist in der Regel vorzuziehen, wenn Sie eine vernünftige Reihenfolge haben. Dies ist jedoch nützlich, wenn Sie dies innerhalb eines Aggregats tun müssen und eine Unterabfrage lieber vermeiden möchten.

Siehe auch diese Frage für einen Fall, in dem dies die natürliche Antwort ist.

0

Verwenden Sie das Folgende 

SELECT timestamp, value, card 
FROM my_table 
ORDER BY timestamp DESC 
LIMIT 1
0
LEMUEL ADANE

Wenn Ihre Tabelle keine ID wie die automatische Inkrementierung von Ganzzahlen und keinen Zeitstempel enthält, können Sie immer noch die letzte Zeile einer Tabelle mit der folgenden Abfrage abrufen.

select * from <tablename> offset ((select count(*) from <tablename>)-1)

So können Sie beispielsweise eine aktualisierte Flat-Datei durchsuchen, den Endpunkt der vorherigen Version suchen/bestätigen und die verbleibenden Zeilen in Ihre Tabelle kopieren.

0
Hoser