MySQL: Knifflige Gruppenabfrage
Kalle_B
- datenbank
Hallöle,
habe diesen Beitrag mit meinem Editor vor-geschrieben.
Das winzige Eingabefenster hier bricht Zeilen, die ich in Gesamtlänge benötige.
Web-Designer scheinen abzustammen von Briefmarken-Designern.
Aber das ist eine andere Baustelle.
Mein Problem: GRUPPENABFRAGE
Mir fehlt die richtige SQL- Idee. Vielleicht hilft mir schon die Formulierung hier.
Habe sie mehrfach überarbeitet. Also los ...
BASISINFORMATION:
Für eine Fachmesse gibt es -BESUCHERGRUPPEN-:
es gibt -EINER-GRUPPEN-:
und es gibt -EINZELBESUCHER-:
Für Gruppenmitglieder gibt es
TABELLE "gruppen":
id
---
114
TABELLE "besucher_zu_gruppen":
id adress_id gruppen_id
-- --------- ----------
74 1807 114 <== Besucher Baumann
95 1808 114 <== Besucher Kübler
Die Gesprächswünsche sind hier:
TABELLE "kontakte":
id besucher_id gruppen_id aussteller_id slot_nr
-- ----------- ---------- ------------- -------
01 1807 114 1532 0 <== mit 1808 zu 1532
02 1807 114 1586 0 <== Gruppenmitglied 1807 allein
03 1808 114 1532 0 <== mit 1807 zu 1532
04 1808 114 1575 0 <== Gruppenmitglied 1808 allein
05 4711 0 1530 0 <== Einzelbesucher Schröder (keine Gruppe)
Die SQL-Abfrage mit besucher_id - aussteller_id soll je nach Input folgenden Output liefern:
Input: 1807 - 1532
Output: 114, 1807 Baumann, 1532, Opel, ...
114, 1808 Kübler, 1532, Opel, ...
Input: 1808 - 1532
Output: 114, 1807 Baumann, 1532, Opel, ...
114, 1808 Kübler, 1532, Opel, ...
Input: 1807 - 1586
Output: 114, 1807 Baumann, 1586, Ford, ...
Input: 4711 - 1530
Output: 0, 4711, Schröder, 1530, A.T.U., ...
Bisher brauche ich dafür 1..3 Abfragen. Wenn die erste kein Ergebnis bringt, formuliere ich die nächste.
Lieben Gruß aus dem Sonnigen Odenwald, Kalle
Das Problem sehe ich in der redundanten Verwendung der gruppen_id. Das ganze wäre SEHR einfach zu lösen, wenn du eine eigene Tabelle für die Gruppen machst und die gruppen_id aus der Tabelle Kontakte einfach entfernst. Dann kannst du doch einfach nach Gruppen oder Einzelpersonen suchen (natürlich für einen bestimmten Gesprächstermin).
Das Problem sehe ich in der redundanten Verwendung der gruppen_id. Das ganze wäre SEHR einfach zu lösen, wenn du eine eigene Tabelle für die Gruppen machst und die gruppen_id aus der Tabelle Kontakte einfach entfernst. Dann kannst du doch einfach nach Gruppen oder Einzelpersonen suchen (natürlich für einen bestimmten Gesprächstermin).
Mir ist gerade aufgefallen, dass du die Tabelle gruppen ja schon hast (wobei die Tabelle "besucher_zu_gruppen" eigentlich reicht). Dann kannst du ja einfach die gruppen_id löschen und stattdessen über die personen gehen.
Mir ist gerade aufgefallen, dass du die Tabelle gruppen ja schon hast (wobei die Tabelle "besucher_zu_gruppen" eigentlich reicht). Dann kannst du ja einfach die gruppen_id löschen und stattdessen über die personen gehen.
Bei Besuchern, die einer Gruppe zugeordnet sind, klappt das ja auch.
Aber was ist mit Einzelbesuchern?
Aber was ist mit Einzelbesuchern?
Da du die Gruppe nicht als input verwendest, ist das auch unerheblich. Hier mal meine Lösung:
SELECT gruppen_id, besucher_id, aussteller_id FROM kontakte LEFT JOIN besucher_zu_gruppen ON kontakte.besucher_id = besucher_zu_gruppen.adress_id WHERE besucher_id = $input1 AND aussteller_id = $input2
Alles andere brauchst du eigentlich nicht.
Gruß
Andi
SELECT gruppen_id, besucher_id, aussteller_id FROM kontakte LEFT JOIN besucher_zu_gruppen ON kontakte.besucher_id = besucher_zu_gruppen.adress_id WHERE besucher_id = $input1 AND aussteller_id = $input2
Da hole ich - wenn vorhanden - die gruppen_id zum Besucher.
Aber ich bekomme _keine_ Information, wieviele Gruppenmitglieder gemeinsam zum Aussteller gehen wollen.
Mit der gruppen_id muss ich
kontakte AS kon2
nach der Kombination kon2.gruppen_id / kon2.aussteller_id befragen.
Als Antwort erhalte ich dann einen (den mir schon bekannten) oder mehrere Besucher.
Ein Einzelbesucher hat jedoch keinen Eintrag in besucher_zu_gruppen. Wie bekomme ich ihn im SQL- Kommando auf die "rechte" Seite, wo sonst die Gruppenmitglieder stehen?
Denn da geht es weiter mit JOINS zum Personenstamm, Anwesenheit, ...
Danke für deinen Ansatz, hilft aber nicht sehr.
LG Kalle
Wie gesagt, ich sehe das Problem immer noch in redundanten bzw. nicht ausreichend normalisierten Tabellen.
Packen wir das Problem nochmal an der Wurzel:
Daraus ergeben sich folgende Tabellen:
Damit werden auch die Abfragen um einiges einfacher.
Gruß
Andi
Wie gesagt, ich sehe das Problem immer noch in redundanten bzw. nicht ausreichend normalisierten Tabellen.
Das wäre möglich.
Packen wir das Problem nochmal an der Wurzel:
- Eine Person kann zu keiner, einer oder mehreren (N) Gruppen gehören, und umgekehrt (N:N Beziehung)
Nein. Eine Person kann zu keiner oder einer Gruppe gehören.
- Eine Person kann zu " " " Gesprächen, und umgekehrt (N:N)
Ja, eine Person kann 0..n Gespräche haben und an einem Gespräch können 1..n Besucher und 1 Aussteller teilnehmen.
- Eine Gruppe kann zu N Gesprächen, ein Gespräch kann aber nur von einer Gruppe besucht werden (N:1).
Hier steckt wohl das Problem. Ein Gespräch kann von einer Gruppe besucht werden _oder_ von einer Person, die der Gruppe 0 (= keine Gruppe) angehört. Ich hätte es einfacher, wenn auch dafür eine Gruppe vorhanden wäre.
Daraus ergeben sich folgende Tabellen:
- Personen 1)
- Gruppen 2)
- Gespräche (oder wie du es nennst) 3)
- Personen_Gruppen 4)
- Personen_Gespräche 5)
Damit werden auch die Abfragen um einiges einfacher.
Gruß, Kalle
Moin!
- Eine Person kann zu keiner, einer oder mehreren (N) Gruppen gehören, und umgekehrt (N:N Beziehung)
Nein. Eine Person kann zu keiner oder einer Gruppe gehören.
Eine Person, die zu "keiner" Gruppe (im Sinne von "mehrere Personen") gehört, gehört immer zu einer Gruppe der Größe 1, die nur diese Person enthält.
Somit erhälst du für jeden Besucher exakt EINE Gruppe (die mindestens eine, eventuell auch mehrere Personen) umfaßt, und hast in deiner Abfrage kein Problem, auf Gruppen oder Einzelpersonen achten zu müssen, weil alles Gruppen sind.
- Sven Rautenberg
yo,
Somit erhälst du für jeden Besucher exakt EINE Gruppe (die mindestens eine, eventuell auch mehrere Personen) umfaßt, und hast in deiner Abfrage kein Problem, auf Gruppen oder Einzelpersonen achten zu müssen, weil alles Gruppen sind.
nein, diesen ansatz würde ich nicht verfolgen, weil es die realität falsch abbildet und meiner meinung nach das problem seiner abfrage nicht löst. personen, die keiner Gruppen angehören sollten einen entsprechenden NULL eintrag erhalten, falls den die zugehörige gruppe auch richtig als 1:n abgebildet wird.
Ilja
echo $begrüßung;
habe diesen Beitrag mit meinem Editor vor-geschrieben.
Das winzige Eingabefenster hier bricht Zeilen, die ich in Gesamtlänge benötige.
Web-Designer scheinen abzustammen von Briefmarken-Designern.
Aber das ist eine andere Baustelle.
Nein, das ist keine Baustelle :-)
In den Benutzer-Einstellungen gibt es im Abschnitt "Neue Postings" Einstellmöglichkeiten für das "Antwortfeld". Das wirkt dann zumindest bis man in die Vorschau wechselt. Und auch da kann man sicherlich noch mit User-CSS im Browser was drehen.
echo "$verabschiedung $name";
In den Benutzer-Einstellungen gibt es im Abschnitt "Neue Postings" Einstellmöglichkeiten für das "Antwortfeld". Das wirkt dann zumindest bis man in die Vorschau wechselt. Und auch da kann man sicherlich noch mit User-CSS im Browser was drehen.
Da braucht man eine Anmeldung?
Die hatte ich vor Monaten mal machen wollen und bin gescheitert. Im Forum konnte ich lesen, dass auch andere User Probleme hatten.
Ich mag aber den lockeren Umgang ohne Anmeldung.
Kalle
ich denke mal laut zum Mitschreiben:
besucher_id = 1660
1.
Ich gehe mit dieser besucher_id in TABELLE "personen", denn die Daten brauche ich auf jeden Fall:
SELECT
per1.id bes_id
,per1.bezeichnung bes_firma
,per1.nname bes_nname
FROM bfp_adressen AS per1
WHERE per1.id = 1660
ERGEBNIS:
bes_id bes_firma bes_nname
1660 Dr. Ing. h.c. F. Porsche AG Baumgärtner
2.
Mit LEFT JOIN hole ich aus TABELLE "besucher_zu_gruppen" die gruppen_id zum Besucher, und die adress_id der anderen Mitglieder:
SELECT
per1.id bes_id
,per1.bezeichnung bes_firma
,per1.nname bes_nname
,''
,grb1.gruppen_id bes_grp
,grb1.adress_id bes_mitgl
FROM bfp_adressen AS per1
LEFT JOIN bfp_gruppen_besucher AS grb1
ON grb1.adress_id = per1.id
WHERE per1.id = 1660
ERGEBNIS:
bes_id;bes_firma;bes_nname;bes_grp;bes_mitgl
1660;Dr. Ing. h.c. F. Porsche AG;Gärtner;183;1660
Das ist eine Sackgasse, denn Gärtner hat noch einen Kollegen, der zur Gruppe gehört.
-- ich merke gerade, dass diese Tipperei ins uferlose ausartet, ich glaube, so ein Thema kann man nicht schriftlich diskutieren.
ABBRUCH
Kalle
yo Kalle,
wie du weiter unten geschrieben hast, kann ein besucher nur zu einer gruppe gehören oder gar keine. somit liegt eine 1:n beziehung vor und die tabelle besucher_zu_gruppen ist überflüssig. indem du die gruppen_id mit in die tabelle adressen mit rein nimmst, deckst du die beziehung ausreichend ab.
folglich würde sich dann auch die tabelle kontakte ändern, dort würde die gruppen_id rausfliegen.
je nachdem ob du dein design ändern willst oder nicht, sieht die abfrage entsprechend aus. wenn ich dein ziel richtig verstanden habe willst du abfragen: zeige mir für einen besucher alle seine gruppenmitglieder, die ebenfalls einen bestimmten aussteller besuchen wollen.
SELECT hier_die_gewünschten_spalten
FROM kontakte k
WHERE k.aussteller_id = $input_aussteller AND
(k.besucher_id= $input_aussteller OR k.id IN
(
SELECT k2.id
FROM kontakte k2
WHERE k2.gruppen_id = k.gruppen_id
AND k2.austeller_id = $input_aussteller
)
)
versuch das mal auf dein jetztiges datendesign anzuwenden. ich kann mich nur nicht mehr erinnern, ob du unterabfragen abfragen kannst, sprich mysql 4.1+ hast.
Ilja
Hallöle, Ilja,
SELECT hier_die_gewünschten_spalten
FROM kontakte k
WHERE k.aussteller_id = $input_aussteller AND
(k.besucher_id= $input_aussteller OR k.id IN
(
SELECT k2.id
FROM kontakte k2
WHERE k2.gruppen_id = k.gruppen_id
AND k2.austeller_id = $input_aussteller
)
)versuch das mal auf dein jetztiges datendesign anzuwenden. ich kann mich nur nicht mehr erinnern, ob du unterabfragen abfragen kannst, sprich mysql 4.1+ hast.
Nöö, habe MySQL 3.23.58. Freut mich irgenwie, dass du es auch mit zwei Abfragen (Subselect) gemacht hast.
Hier jetzt meine Lösung:
// 2006-06-07 AUCH BESUCHERGRUPPE LESEN
$q = "
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SELECT
grb2.gruppen_id grp_id
,grb2.adress_id bes_id
,kon1.id kon_id
,kon1.aussteller_id aus_id
FROM bfp_gruppen_besucher AS grb1
,bfp_gruppen_besucher AS grb2
LEFT JOIN bfp_kontakte AS kon1
ON kon1.besucher_id = grb2.adress_id
AND kon1.aussteller_id = ".$aus_id."
WHERE grb1.adress_id = ".$bes_id."
AND grb2.gruppen_id = grb1.gruppen_id
AND kon1.aussteller_id IS NOT NULL
";
$res_bu1 = mysql_query( $q, $conn_id ); zeigSqlFehler( $act, $q, $conn_id );
// KANN LEER SEIN, WENN KEIN GRUPPENMITGLIED
$where_string = '';
for ( $i=0; $i<mysql_num_rows( $res_bu1 ); $i++ )
{
$row_bu1 = mysql_fetch_array( $res_bu1 );
if ( $i > 0 ) $where_string .= ' OR ';
$where_string .= "id=".$row_bu1['kon_id'];
}
if ( !mysql_num_rows( $res_bu1 ))
{
$where_string = "id=".$row_bu1['kon_id'];
}
$q = "
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
UPDATE ".$db[0]['kontakte']."
SET
storno_kz = 0
,slot_nr = ".$slot_nr."
,sperr_kz = 0
,aussteller2_id = ".$frei_aus_row['id']."
WHERE ".$where_string."
";
echo "<pre>".$q."</pre>\n";
Kalle
yo,
Nöö, habe MySQL 3.23.58. Freut mich irgenwie, dass du es auch mit zwei Abfragen (Subselect) gemacht hast.
naja, die abfrage mit dem subselect ist schon noch eine abfrage. man kann es aber auch mit einem SELFJOIN lösen.
SELECT ....
FROM bfp_kontakte tab1
INNER JOIN bfp_kontakte tab2
ON (tab1.id = tab2.id OR tab1.gruppen_id = tab2.gruppen_id)
WHERE tab1.besucher_id = $input1
AND tab1.austeller_id = $input2
AND tab2.austeller_id = $input2
versuch das mal....
Ilja