Nun ja, schnell & schmutzig:
test=# select * from chemie;
verbindung | element | atomanzahl
-------------+---------+------------
Formaldehyd | C | 1
Formaldehyd | H | 2
Formaldehyd | O | 1
Wasser | H | 2
Wasser | O | 1
(5 rows)
Nun eine Funktion:
create or replace function chemie() returns int as $$
declare
anz_spalten int;
i int;
j int;
k int;
rec record;
sql text;
alt_verbindung text;
begin
select into anz_spalten count(1) as anzahl from chemie group by verbindung order by anzahl desc limit 1;
sql := 'create table chemie_crosstab (verbindung text';
for i in 1 .. anz_spalten loop
sql := sql || ', element' || i || ' text, atomanzahl' || i || ' int';
end loop;
sql := sql || ')';
raise notice '%',sql;
execute sql;
alt_verbindung := '';
k := 0;
sql := '';
for rec in select * from chemie order by verbindung, element loop
k:=k+1;
if alt_verbindung != rec.verbindung then
if sql != '' then
for j in k .. anz_spalten loop
raise notice 'k: %',k;
sql := sql || ',NULL,NULL';
end loop;
raise notice 'sql version 1 %', sql;
execute sql;
k:=0;
sql:='';
end if;
sql := 'insert into chemie_crosstab(verbindung';
for j in 1 .. anz_spalten loop
sql := sql || ',element' || j || ', atomanzahl' || j ;
end loop;
sql := sql || ') values (' || quote_literal(rec.verbindung) || ',' || quote_literal(rec.element) || ',' || rec.atomanzahl;
else
sql := sql || ',' || quote_literal(rec.element) || ',' || rec.atomanzahl;
end if;
alt_verbindung := rec.verbindung;
if k = anz_spalten then
sql := sql || ')';
raise notice 'fuehre aus: %',sql;
execute sql;
k:=0;
sql:='';
end if;
end loop;
for j in k+1 .. anz_spalten loop
sql := sql || ',NULL, NULL';
end loop;
sql := sql || ')';
raise notice 'fuehre zum Schluss aus: %', sql;
execute sql;
return 1;
end;
$$ language plpgsql;
Anwendung:
CREATE FUNCTION
test=*# select * from chemie();
NOTICE: create table chemie_crosstab (verbindung text, element1 text, atomanzahl1 int, element2 text, atomanzahl2 int, element3 text, atomanzahl3 int)
NOTICE: fuehre aus: insert into chemie_crosstab(verbindung,element1, atomanzahl1,element2, atomanzahl2,element3, atomanzahl3) values ('Formaldehyd','C',1,'H',2,'O',1)
NOTICE: fuehre zum Schluss aus: insert into chemie_crosstab(verbindung,element1, atomanzahl1,element2, atomanzahl2,element3, atomanzahl3) values ('Wasser','H',2,'O',1,NULL, NULL)
chemie
--------
1
(1 row)
test=*# select * from chemie_crosstab;
verbindung | element1 | atomanzahl1 | element2 | atomanzahl2 | element3 | atomanzahl3
-------------+----------+-------------+----------+-------------+----------+-------------
Formaldehyd | C | 1 | H | 2 | O | 1
Wasser | H | 2 | O | 1 | |
(2 rows)
Mag sein, daß da noch Fehler drin sind (z.B. beim zweiten Aufruf nörgelt er, daß die Tabelle schon existiert), ich hab das auch nicht weiter getestet. Der Weg sollte aber erkennbar sein.
Daß man, wenn man sowas schreiben will, sich etwas mit der Sprache beschäftigen muß, sollte klar sein.
Andreas