Tabelle neu ordnen

Ich hab ein etwas komplexes Problem und vielleicht sehe ich den Wald vor lauter Bäume nicht, aber ich komme damit gerade echt nicht mehr weiter :confused:

Ich hab folgende Tabelle:

LEVEL1 | LEVEL2 | LEVEL3 | LEVEL4 | | LEVEL5 | LEVEL6
1 0 0 0 0 Wert1
1 1 0 0 0 Wert2
1 1 1 0 0 Wert3
1 1 1 1 0 Wert4
1 2 0 0 0 Wert5
1 2 2 0 0 Wert6
1 2 2 2 0 Wert7

und möchte folgende Ausgabe erreichen:

LEVEL1 | LEVEL2 | LEVEL3 | LEVEL4 | | LEVEL5
Wert1 Wert2 Wert3 Wert4 NULL
Wert1 Wert5 Wert6 Wert7 NULL

Hoffe mal das Beispiel reicht aus…

Nein, ich denke nicht. Wieso erscheinen bei dir in einer einzelnen Zeile mehrere Werte aus unterschiedlichen Zeilen?

Nach welchen Kriterien sortierst du diese Ausgabe überhaupt, ich kann da keinen Sinn sehen.

Im Grunde geht es bei den Daten um Land/Bundesland/Landkreis/Stadt.

Land | Bundesland | Landkreis | Stadt | Name
1 0 0 0 Deutschland
1 1 0 0 Baden-Württenberg
1 1 1 0 Stuttgart
1 1 1 1 Stuttgart
1 1 2 0 Heilbronn
1 1 2 2 Heilbronn

Ausgabe:

Land | Bundesland | Landkreis | Stadt
Deutschland | Baden-Württenberg | Stuttgart | Stuttgart
Deutschland | Baden-Württenberg | Heilbronn| Heilbronn


Fragt mich bitte nicht warum die Daten so angeordnet sind, es ist einfach so :sunglasses:

Eine Abfrage hab ich inzwischen, allerding gibt es Probleme wenn in der Spalte Stadt keine Werte gibt, dann kann es keine Ausgabe geben. Ich bräuchte eine Abfrage die fehlende Daten mit NULL Werte auffüllt.

Land | Bundesland | Landkreis | Stadt
Deutschland | Baden-Württenberg | Stuttgart | Stuttgart
Deutschland | Baden-Württenberg | Heilbronn| NULL

Die Anordnung der Daten ist mehr als bescheiden und daraus resultiert auch dein Problem, die Anfrage ordentlich zusammenzustellen.

Nun, als einfachster Ausweg würde ich dir eine Stored Procedure empfehlen, die du aufrufst und die intern die eigentliche Arbeit erledigt. Dann kannst du ggf. auch mehrere Abfragen ausführen, um fehlende Daten einzusammeln.

Vielleicht hilft dir auch die neu hinzugekommene Rekursion in PostgreSQL 8.4, obwohl mir da auf Anhieb auch kein sauberer Weg einfällt - die Daten sind einfach zu ungeschickt zusammengestellt.

Wenn Du schon eine Abfrage hast, dann könntest Du diese ja hier zeigen, damit wir nicht das Rad zum 2. Mal erfinden müssen. Die fehlenden Daten mit ‘NULL’ aufzufüllen scheint eine Aufgabe für COALESCE() zu sein.


Ansonsten stimme ich ads zu :wink:

Andreas

Ich frag Dich jetzt mal, warum sind die Daten so besch**** angeordnet? Da ist nun echt schwer eine Struktur zu finden - ich finde zumindest keine.

Man könnte es so machen:

test=*# select * from foo;
 id | parent_id | typ |       name
----+-----------+-----+-------------------
  1 |           |   1 | Deutschland
  2 |         1 |   2 | Baden-Württenberg
  3 |         2 |   3 | Stuttgart
  4 |         3 |   4 | Stuttgart
  5 |         2 |   3 | Heilbronn
  6 |         5 |   4 | Heilbronn
  9 |         8 |   4 | Meißen
  8 |         7 |   3 | Meißen
  7 |         1 |   2 | Sachsen
(9 rows)

Für die Typ-Spalte könnte/sollte man noch eine weitere Tabelle nehmen, auf die referenziert wird und die die Tyenbezeichnung (1=Land, 2=Bundesland, …) enthält.

Eine rekursive Abfrage, die das in ‘schön lesbar’ ausgibt könnte dann lauten:

test=*# with recursive re as (select f.* from foo f where name='Deutschland' union all select p.* from foo p join re on (re.id=p.parent_id)) select id, case when typ=1 then 'Land' whentyp=2 then ' Bundesland' when typ=3 then '  Landkreis' when typ=4 then '   Stand'  end as Typ, name from re order by id;
 id |     typ     |       name
----+-------------+-------------------
  1 | Land        | Deutschland
  2 |  Bundesland | Baden-Württenberg
  3 |   Landkreis | Stuttgart
  4 |    Stand    | Stuttgart
  5 |   Landkreis | Heilbronn
  6 |    Stand    | Heilbronn
  7 |  Bundesland | Sachsen
  8 |   Landkreis | Meißen
  9 |    Stand    | Meißen
(9 rows)

Wie gesagt, die Bezeichnungen könnte man noch in einer weiteren Tabelle halten und diese könnte man hier reinjoinen, um sie da Gehampel mit dem case when … zu ersparen.

Mit dieser Struktur könnte man auch Teilbäume leicht abfragen:

test=*# with recursive re as (select f.* from foo f where name='Baden-Württenberg' and typ=2 union all select p.* from foo p join re on (re.id=p.parent_id)) select id, case when typ=1 then 'Land' when typ=2 then ' Bundesland' when typ=3 then '  Landkreis' when typ=4 then '   Stand'  end as Typ, name from re order by id;
 id |     typ     |       name
----+-------------+-------------------
  2 |  Bundesland | Baden-Württenberg
  3 |   Landkreis | Stuttgart
  4 |    Stand    | Stuttgart
  5 |   Landkreis | Heilbronn
  6 |    Stand    | Heilbronn
(5 rows)

Also, falls es noch nicht zu spät ist, stricke das noch mal um.


Andreas

Die Daten wurden von mir nicht so angeordnet, ich vermute einfach, dass es irgendwie historisch gewachsen ist. Deswegen will ich sie ja neu anlegen.

Na, wenn du sie sowieso neu anlegen willst, mach es gleich richtig.
Dann brauchst du dich auch nicht auf eine einzelne Abfrage zum Auslesen der Ursprungsdaten beschränken, die Arbeit passiert ja nur einmalig.

Leider keine einmalige Sache, aber das ist ein anderes Thema. Mit der Erstellung der Daten hab ich leider nichts zu tun.

Ich frag noch mal: wie sieht Deine bisherige Abfrage aus?

Andreas

SELECT level1.area_name AS Land, level2.area_name AS Bundesland, level3.area_name AS Landkreis, level4.area_name AS Stadt, level5.area_name AS Stadtteil FROM tabelle1 AS level1, tabelle1 AS level2, tabelle1 as level3, tabelle1 as level4, tabelle1 as level5 WHERE (level1.areacode_1 = level2.areacode_1) AND (level2.areacode_1 = level3.areacode_1 AND level2.areacode_2 = level3.areacode_2) AND (level3.areacode_1 = level4.areacode_1 AND level3.areacode_2 = level4.areacode_2 AND level3.areacode_3 = level4.areacode_3) AND (level4.areacode_1 = level5.areacode_1 AND level4.areacode_2 = level5.areacode_2 AND level4.areacode_3 = level5.areacode_3 AND level4.areacode_4 = level5.areacode_4) ORDER BY level5.area_name

Das erzeugt aber offensichtlich Bullshit:

test=*# select * from tabelle1 ;
 areacode_1 | areacode_2 | areacode_3 | areacode_4 |     area_name
------------+------------+------------+------------+-------------------
          1 |          0 |          0 |          0 | Deutschland
          1 |          1 |          0 |          0 | Baden-Württenberg
          1 |          1 |          1 |          0 | Stuttgart
          1 |          1 |          1 |          1 | Stuttgart
          1 |          1 |          2 |          0 | Heilbronn
          1 |          1 |          2 |          2 | Heilbronn
          1 |          2 |          0 |          0 | Sachsen
          1 |          2 |          3 |          0 | Meißen
          1 |          2 |          3 |          3 | Meißen
(9 rows)

Und Deine Abfrage dazu:

test=*# select count(1) from (SELECT  level1.area_name, level2.area_name, level3.area_name, level4.area_name, level5.area_name FROM tabelle1 AS level1, tabelle1 AS level2, tabelle1 as level3, tabelle1 as level4, tabelle1 as level5 WHERE (level1.areacode_1 = level2.areacode_1) AND (level2.areacode_1 = level3.areacode_1 AND level2.areacode_2 = level3.areacode_2) AND (level3.areacode_1 = level4.areacode_1 AND level3.areacode_2 = level4.areacode_2 AND level3.areacode_3 = level4.areacode_3) AND (level4.areacode_1 = level5.areacode_1 AND level4.areacode_2 = level5.areacode_2 AND level4.areacode_3 = level5.areacode_3 AND level4.areacode_4 = level5.areacode_4) ORDER BY level5.area_name) foo;
 count
-------
   549
(1 row)

test=*# SELECT level1.area_name, level2.area_name, level3.area_name, level4.area_name, level5.area_name FROM tabelle1 AS level1, tabelle1 AS level2, tabelle1 as level3, tabelle1 as level4, tabelle1 as level5 WHERE (level1.areacode_1 = level2.areacode_1) AND (level2.areacode_1 = level3.areacode_1 AND level2.areacode_2 = level3.areacode_2) AND (level3.areacode_1 = level4.areacode_1 AND level3.areacode_2 = level4.areacode_2 AND level3.areacode_3 = level4.areacode_3) AND (level4.areacode_1 = level5.areacode_1 AND level4.areacode_2 = level5.areacode_2 AND level4.areacode_3 = level5.areacode_3 AND level4.areacode_4 = level5.areacode_4) ORDER BY level5.area_name limit 10;
     area_name     | area_name |     area_name     |     area_name     |     area_name
-------------------+-----------+-------------------+-------------------+-------------------
 Heilbronn         | Heilbronn | Baden-Württenberg | Baden-Württenberg | Baden-Württenberg
 Meißen            | Heilbronn | Baden-Württenberg | Baden-Württenberg | Baden-Württenberg
 Stuttgart         | Heilbronn | Baden-Württenberg | Baden-Württenberg | Baden-Württenberg
 Heilbronn         | Heilbronn | Baden-Württenberg | Baden-Württenberg | Baden-Württenberg
 Sachsen           | Heilbronn | Baden-Württenberg | Baden-Württenberg | Baden-Württenberg
 Meißen            | Heilbronn | Baden-Württenberg | Baden-Württenberg | Baden-Württenberg
 Baden-Württenberg | Heilbronn | Baden-Württenberg | Baden-Württenberg | Baden-Württenberg
 Stuttgart         | Heilbronn | Baden-Württenberg | Baden-Württenberg | Baden-Württenberg
 Deutschland       | Heilbronn | Baden-Württenberg | Baden-Württenberg | Baden-Württenberg
 Deutschland       | Heilbronn | Baden-Württenberg | Baden-Württenberg | Baden-Württenberg
(10 rows)

Andreas