Wie werden Zeilennummern in der PostgreSQL-Abfrage angezeigt?

72

Ich möchte die Beobachtungsnummer für jeden Datensatz anzeigen, der von einer PostgreSQL-Abfrage zurückgegeben wird.

Ich denke, in 8.4 können Fensterfunktionen diese Fähigkeit ausführen.

vol7ron
quelle
Ich denke, ich muss meine eigene Frage favorisieren, damit ich in Zukunft darauf
zurückkommen
30
+1 Dies ist die erste Frage, die ich gesehen habe und die ausschließlich aus Fragen, Antworten und Dialogen einer einzelnen Person besteht.
Xeoncross
2
:) Xeon, du hast mich nur zum Lachen gebracht. Ich komme immer wieder auf diese Frage zurück.
Vol7ron

Antworten:

105
select   row_number() over (order by <field> nulls last) as rownum, *
from     foo_tbl
order by <field>

Wenn keine Bestellung erforderlich ist, kann diese Antwort auch vereinfacht werden:

select row_number() over(), *  -- notice: no fields are needed
from   foo_tbl

SQL Fiddle Proof of Concept

vol7ron
quelle
1
Es scheint , dass , wenn Sie tun over()dann immer es rownumbers schrittweise, wie gibt , 1 2 3 4... um dieses spezielle Ergebnis (wenn es äußern Abfragen sind , dass rearrange Ergebnisse, dann rownum aus best.-nr. werden könnten: stackoverflow.com/a/4812038/32453 , so Das Hinzufügen eines order bykann in diesen Fällen nützlich sein (oder wenn Sie keine Nullen zählen möchten, wie im ersten Beispiel). FWIW.
Rogerdpack
1
Das ist wirklich cool - könnten einige Neulinge für uns Neulinge herausfinden, wie das funktioniert?
zthomas.nc
2
@ zthomas.nc es ist eine Fensterfunktion. Denken Sie an ein bekanntes Glasfenster. Wenn Sie möchten, können Sie dieses Fenster in kleinere Bereiche (Frames) unterteilen. Alle Ergebnisse sind immer noch eindeutig vorhanden, jedoch über die Frames verteilt. Diese Unterteilung ist eine sogenannte Unterteilung, over()wie oben beschrieben. Wenn Sie keine Bedingungen angegeben haben, gibt es einen Bereich für das gesamte Fenster. Window functionssind insofern einzigartig, als sie Berechnungen über die Zeilen eines Frames hinweg anstelle einer gesamten Ergebnismenge durchführen können. Wenn Sie also row_numbernach Geschlecht arbeiten möchten, können Sie Ihr Over verwenden, um nach Geschlecht zu unterteilen.
Vol7ron
Scheint eine große Abfrage erheblich zu verlangsamen
cdyson37
Es sollte keine so große Wirkung haben. Möglicherweise stoßen Sie bei der großen Abfrage auf andere Einschränkungen, z. B. auf einen reduzierten Arbeitsspeicher. Wenn dies ein solcher Faktor ist und sowohl Zeilennummern als auch Leistung erforderlich sind, sollten Sie die Nummern in Ihrer Präsentations- oder Nachbearbeitungsschicht erstellen.
Vol7ron
5

Postgres <8.4

Für Versionen vor 8.4:

SELECT    count(*) rownum, foo.*
FROM      datatable foo
JOIN      datatable bar
          ON (foo.pk_id <= bar.pk_id)
GROUP BY  foo.pk_id, foo.a, foo.b
ORDER BY  rownum
;

-- if there isn't a single unique/primary key field, you can concatenate fields
--    Example: ON (foo.a||foo.b||foo.c <= bar.a||bar.b||bar.c)

Hoffe das hilft jemandem.

SQL Fiddle Proof of Concept


Ein anderer Ansatz

Ich schlage vor, dies um jeden Preis zu vermeiden, wollte es aber für die Nachwelt einbeziehen. Es ist etwas teuer und ich kann mir vorstellen, dass es nicht gut skaliert, aber wenn ein Primärschlüssel nicht in einer Tabelle vorhanden ist (schlechtes Datenbankdesign), sind Ihre Optionen möglicherweise eingeschränkt. In den meisten Fällen wird empfohlen, die Nummerierung auf der Anwendungsebene durchzuführen.

-- Based on basic table w/o primary key
-- CREATE TABLE names ( name as text );

SELECT num, name[num]
FROM (
  select generate_series( 1, (select count(*) from names) ) as num
) _nums,
(
  select array_agg(name) as name from names
) _names

SQL Fiddle Proof of Concept

Gründe, warum es nicht skaliert:

  • Es ist eine schlechte Idee, Ihre Tupel für jede Zeile in ein Array zu packen
vol7ron
quelle
Diese Methode sollte auf jeder SQL Standard-kompatiblen Datenbank
funktionieren
Ich denke, es ist wichtig zu beachten, dass nullWerte sich darauf konzentrieren sollten null. Daher muss coalesce()möglicherweise ein verwendet werden.
Vol7ron
2
Fensterfunktionen sind Teil des SQL: 2003-Standards.
a_horse_with_no_name
Dies wird nicht funktionieren, dies ist Rang nicht Zeile, betrachten Sie 10,6,6,2, Zeilen 1,2,3,4 ,, aber Rang 1,3,3,4 mit Ihrer Anfrage.
Arthur
@Arthur: Was ist dein Primärschlüssel, wofür pk steht. Eine PK muss per Definition eindeutig sein, es sei denn, es handelt sich um eine CK. Lesen Sie auch den Kommentar unter der Abfrage. obwohl es Bedingungen gibt, unter denen es nicht funktioniert (zum Beispiel bin ich nicht sicher, ob Sie Nullwerte verketten können)
vol7ron