Forum: PC-Programmierung Kennt sich jemand mit MySQL aus? Komplizierte Abfrage.


von Gerhard (Gast)


Lesenswert?

Hallo Leute,

ich habe folgende Abfrage in einem PHP-Skript, die seit einem Update des 
MySQL-Servers durch meinen Hosting-Anbieter nicht mehr funktioniert:

SELECT
  mitglied.titel as titel,
  mitglied.vorname as vorname,
  mitglied.zusatz as zusatz,
  mitglied.nachname as nachname,
  mitglied.spitzname as spitzname,
  mitglied.id as mid
FROM
  mitglied
WHERE
  (mitglied.nachname like '%$search%' OR
   mitglied.vorname like '%$search%' OR
   mitglied.spitzname like '%$search%') AND
   (SELECT
      mitglied_status.status
    FROM
      mitglied, mitglied_status
    WHERE
     mitglied.id = mitglied_status.mitglied AND
     mitglied_status.mitglied = mid
    ORDER BY
     mitglied_status.datum DESC
    LIMIT 1) IN ($status)
ORDER BY
  mitglied.nachname,
  mitglied.vorname ASC

Im Prinzip sucht die Abfrage alle Mitglieder aus einer Tabelle, deren 
Mitgliedsstatus in $status enthalten ist und deren Nachname, Vorname 
oder Spitzname den Substring $search enthält.

Da ein Mitglied mehrere Mitglieds-Statusse haben kann (1:n-Beziehung), 
sind Mitglieder und Statusse über eine extra Tabelle verknüpft, diese 
nennt sich mitglied_status.

Das Problem dieser verschachtelten Abfrage ist nun, daß das Feld "mid" 
in der inneren Abfrage nicht mehr bekannt ist. Ich muß irgendwie die 
Mitglieds-ID aus der Hauptabfrage in der Nebenabfrage zur Verfügung 
haben. In der alten Version von MySQL ging das problemlos, die Abfrage 
hat so funktioniert. Wie macht man das jetzt vernünftig?

von Michael A. (micha54)


Lesenswert?

Hallo,

Du musst den beiden Tabellen mitglied jeweils einen Alias gebe, also

select a.titel, a..... from mitglied a

....(select b.....from mitglieg b
     where .... = a.id

Kenne aber eher Oracle und MS-Sql....

Gruss,
Michael

von Peter (Gast)


Lesenswert?

Ich hoffe es ist kein Fehler drin, und ich habe nichts übersehen

SELECT distinct
  m.titel as titel,
  m.vorname as vorname,
  m.zusatz as zusatz,
  m.nachname as nachname,
  m.spitzname as spitzname,
  m.id as mid
FROM
  mitglied m
  join mitglied_status s
     on s.mitglied = m.mid
WHERE
  (mitglied.nachname like '%$search%' OR
   mitglied.vorname like '%$search%' OR
   mitglied.spitzname like '%$search%')
   and s.Status in ( $status )
ORDER BY
  mitglied.nachname,
  mitglied.vorname ASC

von Gerhard (Gast)


Lesenswert?

Danke euch beiden...

Leider geht's so nicht. Das Problem ist folgendes:

Tabelle Mitglied:

1, Hans, Wurst, Würstchen, ...
2, Gertrude, Heckenpenner, Trudchen, ...

Dann die Tabelle mit der Zuordnung Mitglieds-Status zu Mitglied, wobei 
die komplette Historie mit abgespeichert ist, die das Mitglied je hatte. 
Abgespeichert ist der Primärschlüssel von Mitglied (Mitgliedsnummer), 
der Primärschlüssel vom Status (Status-ID) und das Datum, ab wann das 
Mitglied diesen Status hatte.

Also für Status 1 = Juniormitglied, 2 = Seniormitglied, 3 = 
Fördermitglied könnte die Tabelle so aussehen:

Tabelle mitglied_status:

1, 2, 27.12.2005
1, 3, 01.09.2007
2, 1, 24.04.1971
2, 2, 20.03.1982

Ich brauche jetzt bei meiner Abfrage den aktullen Status des Mitglieds. 
Deshalb die innere Abfrage, wo ich absteigend nach Datum sortiere und 
die Anzahl der Einträge auf 1 limitiere. So kriege ich den letzten 
Eintrag für das betreffende Mitglied, also den aktuellen Status des 
Mitglieds.

Wollte ich jetzt Seniormitglieder suchen, deren Spitzname "chen" 
enthält, würde ich also das Trudchen aus dem o.g. Beispiel finden, nicht 
aber Würstchen, denn der war zwar mal Seniormitglied, ist jetzt aber nur 
noch Fördermitglied.

Gar nicht so einfach. Ich brauche das aber möglichst in EINER Abfrage 
und vor allem kann ich leider an der Datenbankstruktur nichts ändern, 
weil auch andere Programme auf die Datensätze zugreifen.

Danke!

von Peter (Gast)


Lesenswert?

gut jetzt habe ich das Problem verstanden (denke ich). 2.Versuch:

SELECT distinct
  m.titel as titel,
  m.vorname as vorname,
  m.zusatz as zusatz,
  m.nachname as nachname,
  m.spitzname as spitzname,
  m.id as mid
FROM
  mitglied m
  join mitglied_status s
     on s.mitglied = m.mid
  join ( select
             mitglied,
             max(Datum) as Datum
          from
             mitglied_status
          group by mitglied
        ) s2
      on s2.mitglied = m.mitglied
      and s.Datum = s2.Datum
WHERE
  (mitglied.nachname like '%$search%' OR
   mitglied.vorname like '%$search%' OR
   mitglied.spitzname like '%$search%')
   and s.Status in ( $status )
ORDER BY
  mitglied.nachname,
  mitglied.vorname ASC

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.