Abfrage-Problem mit PLZ

Abfrage-Problem mit PLZ

am 07.04.2006 04:30:11 von christoph.soellner

Hi *,

habe ein Problem mit deutschen, 5-stelligen PLZ:
Ich erschaffe "Gebiete", die jeweils einen be-
stimmten PLZ-Bereich abdecken. Es können Über-
schneidungen auftreten, und leider kann es sein,
dass bis auf die einzelne, 5-Stellige PLZ ausge-
wählt werden muss. Also sieht meine Tabelle so aus:

ID GEBIET[VC:50] PLZ[UINT:5]
1 Gebiet 1 80000
2 Gebiet 1 80001
3 Gebiet 1 80002
4 Gebiet 1 80003
5 Gebiet 1 80024
6 Gebiet 1 80025
7 Gebiet 1 80026
8 Gebiet 1 80027
9 Gebiet 1 80028
10 Gebiet 2 80002
11 Gebiet 2 80003
11 Gebiet 2 80004
11 Gebiet 2 80005
[...]

Kann ich jetzt mit einer Abfrage die zusammen-
hängenden PLZ-Bereiche herausbekommen? Also:
ERGEBNIS:
NAME PLZVON PLZBIS
Gebiet 1 80000 80003
Gebiet 1 80024 80028
Gebiet 2 80002 80005
[...]

Ich denke, dass es mit einem Self-Join gehen
müßte, ich steh nur grad am Schlauch.

Danke,
Christoph

Re: Abfrage-Problem mit PLZ

am 07.04.2006 11:11:23 von akorthaus

Hallo!

Christoph Soellner schrieb:

> ID GEBIET[VC:50] PLZ[UINT:5]
> 1 Gebiet 1 80000
> 2 Gebiet 1 80001
> [...]
>=20
> Kann ich jetzt mit einer Abfrage die zusammen-
> hängenden PLZ-Bereiche herausbekommen? Also:
> ERGEBNIS:
> NAME PLZVON PLZBIS
> Gebiet 1 80000 80003
> Gebiet 1 80024 80028
> Gebiet 2 80002 80005
> [...]

"GROUP BY" [1] sowie "MIN()" und "MAX()" [2] sollten Dir hierbei helfen.


Grüße
Andreas


[1]: http://dev.mysql.com/doc/refman/4.1/en/select.html
[2]:=20
http://dev.mysql.com/doc/refman/4.1/en/group-by-functions.ht ml#id3102290

Re: Abfrage-Problem mit PLZ

am 07.04.2006 11:16:53 von Christian Kirsch

Andreas Korthaus schrieb:
> Hallo!
>
> Christoph Soellner schrieb:
>
>> ID GEBIET[VC:50] PLZ[UINT:5]
>> 1 Gebiet 1 80000
>> 2 Gebiet 1 80001
>> [...]
>>
>> Kann ich jetzt mit einer Abfrage die zusammen-
>> hängenden PLZ-Bereiche herausbekommen? Also:
>> ERGEBNIS:
>> NAME PLZVON PLZBIS
>> Gebiet 1 80000 80003
>> Gebiet 1 80024 80028
>> Gebiet 2 80002 80005
>> [...]
>
> "GROUP BY" [1] sowie "MIN()" und "MAX()" [2] sollten Dir hierbei helfen.
>

Ich fürchte nein. Er sucht ja die *zusammenhängenden PLZ-Gebiete*.
Weshalb in der Beispielausgabe auch Gebiet 1 zweimal auftaucht.

An den OP: Beschreib doch bitte mal, was Du eigentlich vorhast.
PLZ-Gebiete haben ja AFAIK gar keine Semantik, ob also da Lücken drin
sind oder nicht (bzw. ob sie "zusammenhängen" oder nicht), bedeutet in
der Regel nichts. Was also hast Du vor?

Re: Abfrage-Problem mit PLZ

am 07.04.2006 11:45:25 von Andreas Kretschmer

Andreas
--
Andreas Kretschmer
Linux - weil ich es mir wert bin!
GnuPG-ID 0x3FFF606C http://wwwkeys.de.pgp.net
Deutsche PostgreSQL User Group: http://pgug.de

Re: Abfrage-Problem mit PLZ

am 07.04.2006 12:18:59 von Andreas Kretschmer

Andreas
--
Andreas Kretschmer
Linux - weil ich es mir wert bin!
GnuPG-ID 0x3FFF606C http://wwwkeys.de.pgp.net
Deutsche PostgreSQL User Group: http://pgug.de

Re: Abfrage-Problem mit PLZ

am 07.04.2006 15:39:20 von christoph.soellner

Hi, danke euch für eure Antworten.
> An den OP: Beschreib doch bitte mal, was Du eigentlich vorhast.
> PLZ-Gebiete haben ja AFAIK gar keine Semantik, ob also da Lücken drin
> sind oder nicht (bzw. ob sie "zusammenhängen" oder nicht), bedeutet in
> der Regel nichts. Was also hast Du vor?

Also recht einfach. Das Programm soll benutzt werden,
um reale PLZ-Gebiete zu verwalten. Der Benutzer kann
zu "Gebiet 1" PLZ-Gebiete hinzufügen als [von]-[bis]
oder zb [814*].

Wenn er nun ein Gebiet anklickt, möchte ich möglichst
kompakt darstellen, welche PLZ drinnen sind; hatte er
8* hinzugefügt, wurden 80000-89999 eingebaut, und 10000
Zahlen darzustellen auf der Seite ist nicht gut. Darum
meine Frage.

Außerdem soll der Benutzer eine PLZ oder PLZ-Gruppen
(wiederrum [82*] oder [80001-80006]) in ein anderes
Gebiet verschieben können. Bevor ich anfange, die ganzen
Ausnahmen zu behandeln, erschien es mir zweckmäßiger,
eine (100.000 Einträge) große Liste zu bauen, zumal ich
später noch herausfinden muß, in welchen Gebieten eine
gegebene PLZ drinnen ist.

Es muss auch nicht das sein:
>ERGEBNIS:
> NAME PLZVON PLZBIS
> Gebiet 1 80000 80003

kann auch das sein:
NAME GRENZE
Gebiet 1 80000
Gebiet 1 80003
Gebiet 1 80024
Gebiet 1 80027

Hilft das weiter?
Christoph

Re: Abfrage-Problem mit PLZ

am 07.04.2006 17:07:23 von christoph.soellner

> Man müßte da sicher etwas tiefer in die Kiste mit den Tricks greifen,
> als schnellschuß mit plpgsql mal dieses hier:
> (mit hinreichend aktuellen Versionen von MySQL sicherlich nachbastelbar)
Deine Lösung wäre perfekt. Ich weiß nur nicht, wie ich das FOR-
Statement auflösen soll. Habe da in der Doku zu STORED PROCEDURES
nichts gefunden. Hat jemand eine Idee? Bin hier:

DELIMITER //
CREATE PROCEDURE gibmirplz (OUT gebiet INT(2), OUT plzvon INT(5), OUT plzbis
INT (5))
BEGIN
SET @id = 0;
SET @s = 0;
SET @e = 0;


END;
//
DELIMITER ;

Und ich würde mir nicht so gern ein PGSQL aufsetzen, weil ich
an die Maschine nicht herankomme. Habe nur das MySQL 5.0.19;

Danke,
Christoph

Re: Abfrage-Problem mit PLZ

am 07.04.2006 17:10:02 von christoph.soellner

Hi nochmal,

> Und ich würde mir nicht so gern ein PGSQL aufsetzen, weil ich
> an die Maschine nicht herankomme. Habe nur das MySQL 5.0.19;
Korrektur, habe gerade erfahren, dass auch ein 5.1 kein Problem
wäre. Ist es nun möglich (REPEAT / CURSOR)?

Re: Abfrage-Problem mit PLZ

am 07.04.2006 17:13:28 von Sven Paulus

Christoph Soellner wrote:
> Deine Lösung wäre perfekt. Ich weiß nur nicht, wie ich das FOR-
> Statement auflösen soll. Habe da in der Doku zu STORED PROCEDURES
> nichts gefunden. Hat jemand eine Idee? Bin hier:

Mit CURSORs. Schau Dir mal meine zweite Antwort auf die Loecherfrage
hier an, das ist eigentlich sehr aehnlich (hier: Gruppe, Start-PLZ
merken, aktuelle PLZ merken; weiter; Gruppe mit Vorgaengergruppe
vergleichen, wenn abweichend, dann letzte Gruppe, Start-PLZ, letzte
PLZ ausgeben, letzte PLZ auf aktuelle PLZ setzen; ansonsten letzte
PLZ auf aktuelle PLZ setzen - oder sowas in der Art halt):

http://groups.google.com/group/de.comp.datenbanken.mysql/bro wse_frm/thread=
/f150fc1c32187434/

Re: Abfrage-Problem mit PLZ

am 07.04.2006 18:12:34 von Andreas Kretschmer

Andreas
--
q: why do so many people take an instant dislike to mysql?
a: it saves time (oicu in #postgresql)
Explaining the concept of referential integrity to a mysql user is like
explaining condoms to a catholic (Shadda in #postgresql)

Re: Abfrage-Problem mit PLZ

am 08.04.2006 21:49:03 von christoph.soellner

Jetzt hab ich mal was gebastelt:

DROP PROCEDURE IF EXISTS plzgebiete;
DELIMITER |
CREATE PROCEDURE plzgebiete (OUT geb_pKey INT, OUT plz_von INT, OUT plz_bis
INT)
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE xid, xs, xe INT;
DECLARE ckey, cplz INT;
DECLARE cur CURSOR FOR SELECT geb_pKey, plz FROM plz ORDER BY plz ASC;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;

SET xid = 0;
SET xs = 0;
SET xe = 0;

OPEN cur;
REPEAT
FETCH cur INTO ckey, cplz;
IF xid = 0 THEN
SET xid = ckey;
SET xs = cplz;
SET xe = cplz;
END IF;
IF xid = ckey THEN
SET xe = cplz;
ELSE
SET geb_pKey = xid;
SET plz_von = xs;
SET plz_bis = xe;
SET xid = ckey;
SET xs = cplz;
SET xe = cplz;
END IF;
UNTIL done END REPEAT;
SET geb_pKey = xid;
SET plz_von = xs;
SET plz_bis = xe;
CLOSE cur;
END
|


Nur leider, wenn ich im phpMyAdmin diese Funktion eingeben will:
Bei keiner Datenbank->Leere Fehlermeldung;
Bei Datenbank 'plz': SQL-Error bei DELIMITER, wenn ich den
DELIMITER mit '-- ' wegmache, SQL-Error bei INT DEFAULT 0 in LINE 4.

Kann es also auch nicht testen. Habt ihr vielleicht eine Idee,
was ich da schon wieder falsch mache? DB-Version ist 5.0.19;

Christoph

Re: Abfrage-Problem mit PLZ

am 09.04.2006 00:52:03 von christoph.soellner

Ok, jetzt aber, die PROCEDURE:
--------------------------------------
CREATE PROCEDURE plzgebiete ()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE lastkey, plzs, plze INT;
DECLARE ckey, cplz INT;
DECLARE cur CURSOR FOR SELECT geb_pKey, plz FROM plz ORDER BY geb_pKey
ASC, plz ASC;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
SET lastkey = 0;
OPEN cur;
ml:LOOP
FETCH cur INTO ckey, cplz;
IF (done=1) THEN
LEAVE ml;
END IF;
IF lastkey <> ckey THEN
SET lastkey = ckey;
SET plzs = cplz;
SET plze = cplz;
ITERATE ml;
END IF;
IF (cplz = (plze+1)) THEN
SET plze = cplz;
ELSE
SELECT lastkey, plzs, plze;
SET plzs = cplz;
SET plze = cplz;
END IF;
END LOOP ml;
CLOSE cur;
END
--------------------------------------
Und die Tabelle
################
geb_pKey plz
1 00001
1 00002
1 00003
1 00007
1 00008
1 00009
1 00010
2 00012
2 00013
2 00014
2 00015
2 00018
2 00019
2 00020
################
gibt folgendes Ergebnis (CALL plzgebiete();)

+---------+------+------+
| lastkey | plzs | plze |
+---------+------+------+
| 1 | 1 | 3 |
+---------+------+------+
1 row in set (0.00 sec)

+---------+------+------+
| lastkey | plzs | plze |
+---------+------+------+
| 2 | 12 | 15 |
+---------+------+------+
1 row in set (0.00 sec)

und ich hätte ja gerne dieses Ergebnis:
+---------+------+------+
| lastkey | plzs | plze |
+---------+------+------+
| 1 | 1 | 3 |
| 1 | 7 | 10 |
| 2 | 12 | 15 |
| 2 | 18 | 20 |
+---------+------+------+
und zwar mit dem Aufruf "SELECT * FROM plzgebiete();" oder
so ähnlich, wenn das irgendwie geht. Weil ich später das hier
machen will: "SELECT * FROM plzgebiete() WHERE lastkey = 1".

Was mach ich denn jetzt noch falsch?
Danke,
Christoph