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.
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.
Antworten:
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
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 by
kann in diesen Fällen nützlich sein (oder wenn Sie keine Nullen zählen möchten, wie im ersten Beispiel). FWIW.
over()
wie oben beschrieben. Wenn Sie keine Bedingungen angegeben haben, gibt es einen Bereich für das gesamte Fenster. Window functions
sind insofern einzigartig, als sie Berechnungen über die Zeilen eines Frames hinweg anstelle einer gesamten Ergebnismenge durchführen können. Wenn Sie also row_number
nach Geschlecht arbeiten möchten, können Sie Ihr Over verwenden, um nach Geschlecht zu unterteilen.
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
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:
null
Werte sich darauf konzentrieren sollten null
. Daher muss coalesce()
möglicherweise ein verwendet werden.