jakkob: JOIN mit zwei Bedingungen

Hallo,

ich hätte da mal ne kleiner Anfängerfrage zu JOINS:

Tabllen [Felder] =

user [userid, username]
email [emailid,adresse]
user_email [userid],[emailid]

Ich kann nun mit

  
SELECT userid  
FROM user,email,user_email  
WHERE email.adresse = "meine_email"  
AND user.username = "mein_name"  
AND user_email.userid = user.userid  
AND user_email.emailid = emai.emailid  

nach einem usernamen mit einer ganz bestimmt E-Mail-Adresse suchen.

Wie aber suche ich nach einem ganz bestimmten Username, der ZWEI E-MAil-Adressen haben muss? Wenn ich einfach

  
AND email.adresse = "meine_email_2"  

dranhänge, gehts auf jeden Fall nicht.

Kann mir da Jemand helfen?

Jakob

  1. Wo ist da ein JOIN?

    Du suchst nach einer Zeile, bei der einmal als Mail "A" drinsteht UND bei der als Mail "B" drin steht. Kann ja nicht gehen :-)

    Such dir aus der Mail-Tabelle alle Einträge die entweder A ODER B enthalten und die die entsprechende userid haben.

    1. Wo ist da ein JOIN?

      Achso..der INNER JOIN erfolgt automatisch, da ich drei Tabellen als FROM  angebe.

      Such dir aus der Mail-Tabelle alle Einträge die entweder A ODER B enthalten und die die entsprechende userid haben.

      Aber ODER ist doch genau das, was ich nicht will! Ich will ja UND.
      Man kann das natürlich hintterher im Skipt machen, aber es muss doch egentlich gehen. Wozu normalisier ich denn meine Tabellen, wenn ich hinterher nicht mal so ne ABfrage hinbekomme :-(

      1. Achso..der INNER JOIN erfolgt automatisch, da ich drei Tabellen als FROM  angebe.

        Klar... hab ich verschlafen.

        Aber ODER ist doch genau das, was ich nicht will! Ich will ja UND.

        Naja es kommt drauf an wie man es formuliert. Eigentlich willst du doch den User der beide Adressen hat. Das ist wörtlich formuliert schon ein UND.
        Aber in der Datenbank stehen die nicht in einer Zeile, sondern in zwei. Deswegen musst du beide Zeilen suchen und das geht mit ODER. Deine Klauseln im WHERE beziehen sich aber immer auf die selbe Zeile.

        Mal Beispiel mit einer Zahlenspalte statt String. Was du momentan machst ist:
        Suche alle Zeilen bei denen in der Spalte 3 UND gleichzeitig 4 steht.
        Und das kann ja nicht gehen.

        1. Suche alle Zeilen bei denen in der Spalte 3 UND gleichzeitig 4 steht.
          Und das kann ja nicht gehen.

          Hmm...aber weil ein User ja mehere E-Mail-Adressen haben kann, deswegen habe ich ja normalisiert. Sonst hätte ich mir das ja schenken können.

          Und deswegen müssten halt bei einem JOIN, der ja die Tabellen wieder zusammen führt, in gewisser Weise schon gleichzeitig alle E-Mail-Adressen stehen. Nur  das auslesen, das hab ich noch nicht hinbekommen.

          @steel
          Hört sich schonmal ganz gut an. Bin aber trotz COUNT und HAVING noch nicht auf die Lösung gestoßen.
          Hättest Du vielleicht noch einen kleinen Tipp?

          1. Hmm...aber weil ein User ja mehere E-Mail-Adressen haben kann, deswegen habe ich ja normalisiert. Sonst hätte ich mir das ja schenken können.
            Und deswegen müssten halt bei einem JOIN, der ja die Tabellen wieder zusammen führt, in gewisser Weise schon gleichzeitig alle E-Mail-Adressen stehen.

            Normalisieren war doch gut. Nur deine Abfrage war fehlerhaft gedacht.

            Mal was anderes, erklär doch mal wo die Abfrage eingesetzt werden soll. Normalerweise gehört eine Mailadresse zu genau einem User, d.h. die teilen sich keine Adressen. Vielleicht kann dein Problem ja ganz anders und viel einfacher gelöst werden.

        2. echo $begrüßung;

          » Aber ODER ist doch genau das, was ich nicht will! Ich will ja UND.
          Naja es kommt drauf an wie man es formuliert. Eigentlich willst du doch den User der beide Adressen hat. Das ist wörtlich formuliert schon ein UND.
          Aber in der Datenbank stehen die nicht in einer Zeile, sondern in zwei. Deswegen musst du beide Zeilen suchen und das geht mit ODER. Deine Klauseln im WHERE beziehen sich aber immer auf die selbe Zeile.

          Eine Bedingung wirkt jeweils auf eine Zeile. Wenn einer zwei Adressen hat, sind das jedoch zwei Zeilen. Die Zeilen stehen sozusagen untereinander und die Bedingung wirkt nebeneinander. Dieses Problem kann man mit einem Selfjoin lösen. Man muss also die email-Tabelle noch ein zweites Mal, diesmal aber mit Alias joinen und dann die erste Bedingung auf email.adresse und die zweite auf [aliasname].adresse testen lassen.

          echo "$verabschiedung $name";

          1. Man muss also die email-Tabelle noch ein zweites Mal, diesmal aber mit Alias joinen und dann die erste Bedingung auf email.adresse und die zweite auf [aliasname].adresse testen lassen.

            Hi,
            und wenn einer dann drei E-Mail-Adressen hat, muss ich drei JOINS machen? Und wenn ich gar nicht weiß, wie viele E-Mails Jemand hat? Dass das so umständlich ist...

            Ich will die DB ja fragen: Gibts es einen User der "Name" heißt und E-Mail_Adresse "Adresse1", "Adresse2", etc. hat (unbekannte Anzahl der E-Mail-Adressen nach der ich suche )

            Was ist denn eure Meinung? Vielleicht doch per Skript:

            1.Userid(s) zum gesuchten Namen abfragen
            2.Userid(s) zu den gesuchten E-Mail-Adressen abfragen
            3.Prüfen ob es eine userid gibt, die für alle E-Mailadressen gültig ist
            4.Prüfen ob diese uderid(s) zu denen der Namen passen

            Oh, Mann. Klingt auch nicht gerade berauschend....
            Also werde ich wohl doch nach dedlfix' Methode probieren.
            (Wenn nich noch Jemand mit der einfachen Lösung kommt, auf die ich eigentlich gehofft hatte)

            Jakkob

            1. echo $begrüßung;

              » Man muss also die email-Tabelle noch ein zweites Mal, diesmal aber mit Alias joinen und dann die erste Bedingung auf email.adresse und die zweite auf [aliasname].adresse testen lassen.
              und wenn einer dann drei E-Mail-Adressen hat, muss ich drei JOINS machen? Und wenn ich gar nicht weiß, wie viele E-Mails Jemand hat? Dass das so umständlich ist...

              Da du gezielt nach Adressen suchst und nicht einfach nur "User mit n beliebigen Adressen" haben willst, wäre das eine Möglichkeit. Eine andere ist, mit WHERE adresse=a OR adresse=b OR ... erstmal die Datensätze auf die interessierenden n Email-Adressen einzuschränken. Jeder Satz dieser Datenmenge enthält eine Adresse und einen Verweis auf den User. Ein User, der n Mal auftaucht, hat also alle n Adressen. Einen der weniger als n Mal auftaucht willst du nicht haben. Die Anzahl zu ermitteln, kannst du über den User gruppieren und mit der HAVING-Klausel die User rausfiltern, die n Mal auftauchen.

              Ich will die DB ja fragen: Gibts es einen User der "Name" heißt und E-Mail_Adresse "Adresse1", "Adresse2", etc. hat (unbekannte Anzahl der E-Mail-Adressen nach der ich suche )

              Den Namen noch mit reinzubringen sollte nicht das Problem darstellen. Auf jeden Fall musst du die Abfrage je nach Bedarf (sprich: Anzahl der Adressen) umschreiben.

              echo "$verabschiedung $name";

              1. Da du gezielt nach Adressen suchst und nicht einfach nur "User mit n beliebigen Adressen" haben willst, wäre das eine Möglichkeit. Eine andere ist, mit WHERE adresse=a OR adresse=b OR ... erstmal die Datensätze auf die interessierenden n Email-Adressen einzuschränken. Jeder Satz dieser Datenmenge enthält eine Adresse und einen Verweis auf den User. Ein User, der n Mal auftaucht, hat also alle n Adressen. Einen der weniger als n Mal auftaucht willst du nicht haben. Die Anzahl zu ermitteln, kannst du über den User gruppieren und mit der HAVING-Klausel die User rausfiltern, die n Mal auftauchen.

                Ahh, das hört sich sehr gut an. So werd ich das machen. Ich war halt als Anfänger irgendnwie der Meinung, sowas müsste Standard sein und es deswegen auch Standardlösungen dafür geben ...
                So kommt auch alles zusammen: Encoders OR kommt genauso zum Einsatz wie Steels Having/Group :-)

                Auf jeden Fall musst du die Abfrage je nach Bedarf (sprich: Anzahl der Adressen) umschreiben.

                Okay, das mache ich eh schon mit if($whatever) $query.="whatever more"...

                Vielen Dank,
                jetzt bekomm ichs hin (inshallah)
                Jakkob

    2. Wo ist da ein JOIN?

      Ein impliziter inner Join. Dort. Ganz deutlich! In der Where Bedingung.

      Du suchst nach einer Zeile, bei der einmal als Mail "A" drinsteht UND bei der als Mail "B" drin steht. Kann ja nicht gehen :-)

      Will er nicht. Er will User die 2 Adressen haben.

      --
      "Die Diebesgilde beklagte sich darueber, dass Mumm in aller Oeffentlichkeit behauptet hatte, hinter den meisten Diebstaehlen steckten Diebe."
            - T. Pratchett
      1. Will er nicht.

        Ich weiß. Aber er macht es trotzdem ;-) Sollte ein Hinweis sein, was da aktuell steht.

  2. Hi!

    am anfang hab ich gedacht: 'Wasn bloedes Konstrukt. Wieviel Mailadressen hat den ein User fuer gewoehnlich?' Und dann war genau das dein Problem. :) So kann man sich irren.

    Hast Dich mal mit Having beschaeftigt? Having und count sollten die richtigen Kumpel fuer dein kleines Problem sein.

    --
    "Die Diebesgilde beklagte sich darueber, dass Mumm in aller Oeffentlichkeit behauptet hatte, hinter den meisten Diebstaehlen steckten Diebe."
          - T. Pratchett