Tabellenzeilen nach IDs clustern

Ich habe eine Tabelle mit einigen Millionen eindeutigen, aber nicht fortlaufenden IDs.

ID Wert
1 x
3 xx
6 oi
9 üp
18 xx
33 zz
44 ii
45 zz

Nun hätte ich gerne einen Query, der mir die Zahl der Ergebnisse in 10er-Clustern ausgibt, also die zahl der IDs von 0-9, 10-19, 20-29 usw ausgibt, als Ergebnis sollte also rauskommen:

0-10 4
10-19 1
20-29 0
30-39 1
40-49 2

usw usf. - die Spalte “Wert” ist hier völlig uninteressant.

Ich habe das bisher über ein Perlscript gemacht, aber ein 100er-Clustering bei 60.000.000 Zeilen ist damit eine doch recht langwierige weil mit 600.000 Queries verbundene Sache…

Hat jemand eine Idee, wie ich das mit SQL hinbekomme? - Performance ist nicht unbedingt notwendig, nur schneller als 600.000 queries (=einige stunden) sollte es sein.

Thomas



test=*# select * from foo;
 id
----
  1
  2
  4
  5
  6
  7
  9
 10
 11
 13
 17
 20
 30
 50
(14 rows)

test=*# select s||'-'||s+10, count(1) from foo, generate_series(0,100,10)s where id between s and s+10 group by 1 order by 1;
 ?column? | count
----------+-------
 0-10     |     8
 10-20    |     5
 20-30    |     2
 30-40    |     1
 40-50    |     1
 50-60    |     1
(6 rows)

Andreas

select s||‘-’||s+9, count(1) from foo, generate_series(0,100,10)s where id between s and s+9 group by 1 order by 1;

generate_series war mir neu. Funktioniert aber toll!
Dauert bei rund 2 Millionen IDs von 0-60 Mio in einer
1000er-Clusterung rund drei Sekunden!

Ich kanns noch nicht ganz fassen!

Danke! Danke! Danke.

tom

Ja, das ist in der Tat nett. Damit kann man z.B. auch Zeiträume bilden (gruppieren nach Woche oder 4 Stunden oder sowas) und viele andere Dinge. Ist aber kein natives SQL, aber gut geeignet, um MySQL-Benutzer grün vor Neid werden zu lassen…


@ads: unbedingt in Deinem Buch erwähnen!!1!

Andreas

Hallo Andreas,

Zeiträume gruppieren??? klingt top! Kannst du eventl. noch ein beispiel dafür bringen? Wär klasse. weil so richtig verstehen tu ich die funktion noch nicht…

Grüße
beho



test=*# select current_date + s*'1 week'::interval from generate_series(0,10)s;
      ?column?
---------------------
 2007-10-24 00:00:00
 2007-10-31 00:00:00
 2007-11-07 00:00:00
 2007-11-14 00:00:00
 2007-11-21 00:00:00
 2007-11-28 00:00:00
 2007-12-05 00:00:00
 2007-12-12 00:00:00
 2007-12-19 00:00:00
 2007-12-26 00:00:00
 2008-01-02 00:00:00
(11 rows)

Sowas halt. Du kannst das, was generate_series() liefert, für alles mögliche verwenden, wo man Serien von irgendwas braucht. Das Resultat ist eine Tabelle, die man auch ver-join-en kann.

Andreas