weko321: mehrfache Abfage von Tabellen

Hallo,

ich komme mit folgendem Problem trotz intensiver Suche im Forum sowie GOOGLE nicht weiter.

Betroffen sind drei Tabellen (FIRMA, FIRMA_PROJEKT, PROJEKT)

Die Tabelle FIRMA enthält die Firmenstammdaten, die Tabelle PROJEKT die Projektstammdaten, die Tabelle FIRMA_PROJEKT stellt die Verbindung her,
d.h. in der Tabelle FIRMA_PROJEKT gibt es zwei Spalten, wobei die erste die FirmenID und die zweite die Projektnummer beinhaltet. Die Spalte Projektstatus ist in diesem Zusammenhang nicht relevant.

Durch dieses Konstrukt ist es möglich, beliebig vielen Firmen beliebig viele Projekte zuzuordnen.

Ich möchte nun gezielt nach Firmen suchen, welche mehrere Projekte
zugeordnet haben, was ich mit untenstehendem Statement erfolglos versucht habe zu realisieren.
Die Suche nach einem Projekt funktioniert einwandfrei, bei der Kombination zweier oder mehrerer erhält man immer eine leere Menge als Ergebnis.

Vielen Dank für euere Hilfe !

$OrderFeld = "FIRMA.Firmenname";

if (isSet($kosmetik) && ($kosmetik == "X"))
  $SelKosmetik = "and FIRMA.FNr = FIRMA_PROJEKT.FNr and FIRMA_PROJEKT.ProjektNr = 7 and FIRMA_PROJEKT.ProjektStatus > 3";

if (isSet($nail) && ($nail == "X"))
  $SelNail = "and FIRMA.FNr = FIRMA_PROJEKT.FNr and FIRMA_PROJEKT.ProjektNr = 29 and FIRMA_PROJEKT.ProjektStatus > 3";

if (isSet($feet) && ($feet == "X"))
  $SelFeet = "and FIRMA.FNr = FIRMA_PROJEKT.FNr and FIRMA_PROJEKT.ProjektNr = 90 and FIRMA_PROJEKT.ProjektStatus > 3";

if (isSet($hair) && ($hair == "X"))
  $SelHair = "and FIRMA.FNr = FIRMA_PROJEKT.FNr and FIRMA_PROJEKT.ProjektNr = 38 and FIRMA_PROJEKT.ProjektStatus > 3";

if (isSet($accessoires) && ($accessoires == "X"))
  $SelAccessoires = "and FIRMA.FNr = FIRMA_PROJEKT.FNr and FIRMA_PROJEKT.ProjektNr = 217 and FIRMA_PROJEKT.ProjektStatus > 3";

$abfrage = sprintf ("%s %s %s %s %s %s %s %s %s %s",
             "select FIRMA.FNr, FIRMA.KdNr, FIRMA.Firmenname, FIRMA.Zusatz, FIRMA.Url, ADRESSE.Strasse,",
             "       ADRESSE.PLZ, ADRESSE.Ort",

"from   FIRMA, ADRESSE, FIRMA_PROJEKT",

"where ( ADRESSE.Ort LIKE '%$Ort%' OR ADRESSE.Plz LIKE '$Ort%' ) and FIRMA.Adresse = ADRESSE.AdrIndex",
             $SelKosmetik,
             $SelNail,
             $SelHair,
             $SelFeet,
             $SelAccessoires,

"order by $OrderFeld");

$res = mysql_query($abfrage);
  $num=mysql_num_rows($res);

  1. Hallo,

    anbei - als Zusatzinfo - die Tabellenstrukturen. Selbige sind hier aus Platzgründen auf die nötigen Spalten reduziert.

    Das Konstrukt mit der Zwischentabelle gibt mir - wie bereits erwähnt die Möglichkeit n:m Beziehungen abzubilden.

    Möchte ich nun wissen, welche Firmen ein Kosmetikstudio ( ProjektNr 7 ) betreiben, funktioniert mein Statement ganz gut und ich erhalte - mit unten genannten beispielhaften Tabellen - als Ergebnis die Firmennummern 1001 - 1005 ( also alle ).

    Ein Kosmetik- UND ein Nagelstudio ( ProjektNr 29 ) betreiben die Firmen 1001, 1002,1005.

    Dieses Ergebnis - sowie die Ergebnisse der anderen Kombinationen - erhalte ich mit meinem Statement nicht.

    Meine Frage ist nun, wie könnte in diesem Falle das konkrete Statement aussehen?

    Nochmals vielen Dank im Voraus !

    Tabelle FIRMA

    FNr Firmenname
    ------------------------------------
    1001 Hans Huber
    1002 Martin Müller
    1003 Lisa Zacherl
    1004 Sabrina Feist
    1005 Renate Bimmler

    Tabelle PROJEKT

    ProjektNr ProjektName
    -----------------------------------
    7 Kosmetikstudio
    29 Nagelstudio
    90 Fusspflegestudio
    38 Haarstudio
    217 Accessoires

    Tabelle FIRMA_PROJEKT

    FNr ProjektNr
    -----------------------------------
    1001 7
    1001 29
    1001 38
    1002 7
    1002 29
    1003 7
    1004 7
    1004 90
    1004 38
    1004 217
    1005 7
    1005 29
    1005 217

  2. Betroffen sind drei Tabellen (FIRMA, FIRMA_PROJEKT, PROJEKT)

    Ich möchte nun gezielt nach Firmen suchen, welche mehrere Projekte
    zugeordnet haben

    Unterabfragen: Erst nach Projekt 1 suchen, dann darin nach Projekt 2 suchen.

  3. yo,

    erst einmal immer wichtig zu sagen, welches dbms und welche version. dann ist es viel besser, wenn du reinen sql code postets und nicht den ganzen programm quatsch mit variablen, die wir nicht einsehen können.

    und zum anderen ist es wahrscheinlich nur eine fragen der richtigen verknüpfung. ich gehe mal davon aus, dass die drei tabellen über ihre schlüssel richtig miteinander verbunden sind.

    dein problem ist wahrscheinlich, dass du zu allem den AND Operator benutzt. aber teilweise den OR einsetzen musst, um unterschiedliche projekte mit anforderungen zu bekommen. mach mal aus den ersten AND'S in den if-abfragen ein OR.

    Ilja

  4. Du gehst mit

      
    SELECT  
     Projekt_Firma_Firma_ID,  
     count(Projekt_Firma_Firma_ID) as Anzahl  
    FROM  
     Projekt_Firma  
    GROUP BY  
     Projekt_Firma_Firma_ID  
    HAVING  
     (COUNT(Projekt_Firma_Firma_ID) > 1)  
    
    

    auf die "n:m"-Tabelle um herauszufinden, welche Firmen mehr als ein Projekt haben. Vorausgesetzt wird dabei die EIndeutigkeit der Beziehung, also dass Projekte und Firmen nicht doppelt miteinander verknüpft sind und es nur so aussieht, als ob eine Firma mehr als ein Projekt hat.

    Darum vielleicht besser (wir kennen ja nicht die Datenqualität ;):

      
    SELECT  
     Projekt_Firma_Firma_ID,  
     count(Projekt_Firma_Firma_ID) as Anzahl  
    FROM  
     (  
     SELECT DISTINCT  
      Projekt_Firma_Firma_ID,  
      Projekt_Firma_Projekt_ID  
     FROM  
      Projekt_Firma  
     )  
    GROUP BY  
     Projekt_Firma_Firma_ID  
    HAVING  
     (COUNT(Projekt_Firma_Firma_ID) > 1)  
    
    

    Jetzt haben wir die Firma_ID(s), die wir referenzieren können in der Hauptabfrage:

      
    SELECT  
     Firma_ID,  
     Firma_Name            -- u.s.w.  
    FROM  
     Firma  
    WHERE  
     (  
     Firma_ID in  
      (  
      SELECT  
       Projekt_Firma_Firma_ID  
      FROM  
       (  
       SELECT DISTINCT  
        Projekt_Firma_Firma_ID,  
        Projekt_Firma_Projekt_ID  
       FROM  
        Projekt_Firma  
       )  
      GROUP BY  
       Projekt_Firma_Firma_ID  
      HAVING  
       (COUNT(Projekt_Firma_Firma_ID) > 1)  
      )  
     )  
    
    
    1. Hallo King Lully,

      ganz herzlichen Dank für Deine schnelle Hilfe !

      Ich habe dieses Problem in mehreren Foren gepostet und

      • von Deiner Antwort abgesehen - nur arogantes bzw. inkompetentes
        BlaBla geerntet.

      Eigentlich schade !

      Nochmals ganz herzlichen Dank, ich werde es umgehend testen und Dir dann berichten.

      1. yo,

        Ich habe dieses Problem in mehreren Foren gepostet und

        • von Deiner Antwort abgesehen - nur arogantes bzw. inkompetentes
          BlaBla geerntet.

        die lösung von ihm wird dir wenig nützen, da du nicht nach firmen suchst, die mehrere projekte haben, sondern firmen zu fest vorgegebenen unterschiedlichen projekten. wie ich bereits geschrieben hatte verknüpfst du die verschiedenen bedingungen falsch.

        zum einen solltest du die join bedingung and FIRMA.FNr = FIRMA_PROJEKT.FNr aus den variablen rausnhemen, und in die abfrage nur einmal schreiben.

        zum anderen musst du den OR Operator verwenden und Klammern setzen, wie ich arroganter Idiot, der nur blabla erzählt, bereits sagte.

        SELECT F.FNr, F.KdNr, F.Firmenname, F.Zusatz, F.Url, A.Strasse, A.PLZ, A.Ort
        FROM FIRMA F, ADRESSE A, FIRMA_PROJEKT FP
        WHERE F.FNr = FP.FNr
        AND F.Adresse = A.AdrIndex
        AND (A.Ort LIKE '%$Ort%' OR A.Plz LIKE '$Ort%' )
        AND
        (
        FP.ProjektNr = 7 AND FP.ProjektStatus > 3
        OR
        FP.ProjektNr = 29 AND FP.ProjektStatus > 3
        OR
        FP.ProjektNr = 90 and FP.ProjektStatus > 3
        OR
        FP.ProjektNr = 38 and FP.ProjektStatus > 3
        )

        den oberen teil der abfrage kannst du so lassen, wie er ist, den unteren kannst du dynamisch mit deinen variablen befüllen.

        ich habe fertig....

        Ilja

        1. Ich habe dieses Problem in mehreren Foren gepostet und

          • von Deiner Antwort abgesehen - nur arogantes bzw. inkompetentes
            BlaBla geerntet.

          die lösung von ihm wird dir wenig nützen, da du nicht nach firmen suchst, die mehrere projekte haben, sondern firmen zu fest vorgegebenen unterschiedlichen projekten. wie ich bereits geschrieben hatte verknüpfst du die verschiedenen bedingungen falsch.

          Du scheinst die Anforderung besser zu kennen als der Fragesteller, wir haben doch ganz klar ein "Ich möchte nun gezielt nach Firmen suchen, welche mehrere Projekte zugeordnet haben, was ich mit untenstehendem Statement erfolglos versucht habe zu realisieren." zu lesen bekommen.

          Ein Tipp: Wenn die Anforderung ausreichend beschrieben worden ist, bringt es nichts eventuell mitgelieferten Code zu analysieren um herauszufinden, was der Fragesteller unter Umständen wirklich erreichen will. (Das Sprachliche geht so zu sagen vor, also hier killt der Code nicht die white paper, sondern andersrum. ;)

          1. yo,

            Du scheinst die Anforderung besser zu kennen als der Fragesteller, wir haben doch ganz klar ein "Ich möchte nun gezielt nach Firmen suchen, welche mehrere Projekte zugeordnet haben, was ich mit untenstehendem Statement erfolglos versucht habe zu realisieren." zu lesen bekommen.

            egal ob nun alle kritereien gleichzeit oder nur mindestens einer zutreffen soll, die problematik bleibt letzlich die gleiche, weswegen er auch eine leere datenmenge bekommt. er hat die bedinungen logisch falsch miteinander verknüpft. eine ergebnisdatensatz kann nicht gleichzeitg mehrere projekten zugeordnet sein und somit ist der AND Operator fehl am platz. genau das erzeugt die leere ergebnismenge. darauf habe ich mich fokusiert, ist aber offensichtlich nicht gut beschrieben von mir.

            wenn nun alle bedinungen gleichzeitig zutreffen sollen, dann bleibt die abfrage mit dem OR operator so bestehen, wie ich sie geschrieben habe. genau darin besteht meiner meinung nach der denkfehler, dass er zwar alle gleichzeitig haben will, aber trotzdem den OR einsetzen muss. das mag auf den ersten blick ein wenig schief klingen, führt aber zum ergebnis.

            das einzige, was man an meiner ersten abfrage ändern muss, ist eine korrelierte unterabfrage in der WHERE klausel, welche die anzahl der treffer einer firmen_id prüft, in diesem falle auf 4, sprich:

            SELECT F.FNr, F.KdNr, F.Firmenname, F.Zusatz, F.Url, A.Strasse, A.PLZ, A.Ort
            FROM FIRMA F, ADRESSE A
            WHERE F.Adresse = A.AdrIndex
            AND (A.Ort LIKE '%$Ort%' OR A.Plz LIKE '$Ort%' )
            AND 4 =
            (
             SELECT COUNT(*) FROM FIRMA_PROJEKT FP
             WHERE F.FNr = FP.FNr
             AND
             (
             FP.ProjektNr = 7 AND FP.ProjektStatus > 3
             OR
             FP.ProjektNr = 29 AND FP.ProjektStatus > 3
             OR
             FP.ProjektNr = 90 and FP.ProjektStatus > 3
             OR
             FP.ProjektNr = 38 and FP.ProjektStatus > 3
             )
            )

            man kann sehen, dass die bedinungen immer noch logisch mit OR verbunden sind.

            was dein tipp betrifft, die fachlichkeit ist immer wichtig zu kennen, ohne zweifel. aber wichtig ist es dann auch, die problemtaiken dabei zu erkennen und richtig umzusetzen. und ich sehe in deinem ansatz keine hinweis auf das kernproblem.

            Ilja

            1. Wir haben eben die Frage beantwortet, lustigerweise kam danach noch eine Menge Code, die wir uns bis jetzt nicht angeschaut haben und auch nicht mehr anschauen werden und eine "Zusatzinfo" ( https://forum.selfhtml.org/?t=144472&m=937499 ), die wir gerade mal überflogen haben, die aber alles eher unklarer zu machen scheint. Wir verstehen auch nicht Deine Interpretation der Fragestellung, es gibt da zwei Möglichkeiten: 1.) Du bist auf dem falschen Dampfer oder 2.) Du bist ein "Weko"-Versteher und belohnst seine dann völlig an der Sache vorbeigehende Fragestellung und hast zu Recht Undank erhalten.

              1. yo,

                schau dir doch mal den einen satz seiner zusatzinfo an, die du gerade verlinkt hast:

                "Ein Kosmetik- UND ein Nagelstudio ( ProjektNr 29 ) betreiben die Firmen 1001, 1002,1005."

                da hat er das "und" sogar explizit gross geschrieben und dann in seine abfrage das auch mit AND umgesetzt. und genau darin besteht die problematik, warum er immer wieder mit dem AND operator eine leere ergebnismenge bekommt, weil ein datensatz der ergebnismenge nicht <gleichzeitig> in zwei verschiedenen projekten vorkommen kann. das ist das kernproblem seiner abfrage, dass ich ihn vermitteln wollte. weswegen er dann gleich ungeduldig wurde und alles als blabla abtut....

                aber helfen würde ihn der hinweis schon, nicht AND, sondern den OR operator zu benutzen. du kannst das glauben oder aber auf deinen hohen thron sitzen bleiben.

                Ilja

                1. Hallo Ilja,

                  mir ist technisch schon klar, dass es mit AND nicht gehen kann.

                  Nur leider habe ich keine Ahnung wie es sonst gehen soll.

                  Ich denke, ich habe mein Problem (incl. Beispieltabellen) nun wirklich sauber beschrieben und kann mir kaum vorstellen, dass ea für ein derartig "alltägliches" Problem keinen Lösungsansatz gibt.

                  Was bitte nicht falsch verstanden sein soll, ich selbst bin ja am wenigsten in der Lage eine Lösung zu finden.

                  1. yo,

                    Ich denke, ich habe mein Problem (incl. Beispieltabellen) nun wirklich sauber beschrieben

                    dein problem hast du gut beschrieben, aber ein paar punkte sind für uns leser immer einfacher. erstens programm-code nicht mit sql abfragen vermischen, wenn es nur um die abfrage geht. zweitens immer das dbms und die version mit angeben. dann kann man sich leichter auf das problem fokusieren.

                    und kann mir kaum vorstellen, dass ea für ein derartig "alltägliches" Problem keinen Lösungsansatz gibt.

                    es gibt sicherlich eine lösung, hast du den meine letzte abfrage schon ausprobiert, bzw. welches falsche ergebnis zeigt es an oder welche fehlermeldung. nur weil man nicht sofort auf die lösung kommt, ist das kein grund, die flinkte ins korn zu werfen.

                    Ilja

        2. Hallo Ilja,

          danke auch für Deine Hilfe !

          Es ist nur so - wenn ich ganz ehrlich sein darf -, dass Dein Ansatz das Problem nicht wirklich löst.

          Auf die von Dir dargestellte Lösung bin ich selbst schon gekommen- sie liegt ( bei schnellem Hinschauen ) ja auch nahe.

          In Deinem Ansatz besteht die Ergebnissmenge aus jenen Firmen, welche in einem bestimmten Ort ENTWEDER ein Nagel- ODER ein Kosmetik- ODER ein Fufpflege- ODER ein Haarstudio betreiben.

          Ich ( bzw. die Besucher meines Portals ) möchten aber zb. in München alle Kosmetikstudios finden, welche auch Nägel machen, d.h. ProjNr 7 AND ProjNr. 29 .

          Und genau diese Anforderung konnte ich bis dato nicht lösen.

          Vielleicht kannst Du mir dabei helfen.

          Vielen Dank schon mal im Voraus.

          1. yo,

            Und genau diese Anforderung konnte ich bis dato nicht lösen.

            hast du den schon die modifizierte abfrage ausprobiert ? die problematik ist letztlich die gleiche.

            Ilja

    2. yo,

      Vorausgesetzt wird dabei die EIndeutigkeit der Beziehung, also dass Projekte und Firmen nicht doppelt miteinander verknüpft sind und es nur so aussieht, als ob eine Firma mehr als ein Projekt hat.

      dafür brauchst du keine weitere unterabfrage in die FROM klausel einbauen. da du bereits über die firmen_id gruppierst, kann man sich das zu nutze machen. ersetze einfach in beiden count-funktionen die firmen_id und setze dort ein DISTINCT projekt_id ein und du bekommst ohne zusätzliche unterabfragen nur distincte werte über die beiden spalten gezählt.

      Ilja

    3. Hallo King Lully,

      habe Deinen Lösungsansatz probiert und Probleme bekommen.

      Wahrscheinlich liegt das nicht zuletzt daran, dass ich meine Fragen etwas "unsauber" formuliert habe.

      Ich ( bzw. die Besucher meines Portals ) möchten zb. in München alle Kosmetikstudios finden, welche auch Nägel machen, d.h. ProjNr 7 AND ProjNr. 29 .

      Und genau diese Anforderung konnte ich bis dato nicht lösen.

      Gibt es dafür eine Lösung ?

      Schon mal vielen Dank !

      1. Ich ( bzw. die Besucher meines Portals ) möchten zb. in München alle Kosmetikstudios finden, welche auch Nägel machen, d.h. ProjNr 7 AND ProjNr. 29 .

        Sei bitte mal so lieb und beschreibe mit ein paar Sätzchen, was Du wirklich benötigst. Ein Beispiel reicht mir da nicht. Welche Art von Suchabfragen benötigst Du? Welche Suchparameter? Besonderheiten? (Das Datendesign ist durchaus verstanden, dazu bitte nichts mehr schreiben.)

        1. Hallo,

          erst mal vielen Dank für Deine Mühen !

          Ich habe nun aus anderer Quelle ein etwas modifiziertes Statement, was die Anforderungen wunderbar erfüllt!

          SELECT f.Firmenname, f.KdNr, a.Ort
          FROM FIRMA AS f, ADRESSE AS a
          INNER JOIN FIRMA_PROJEKT AS fp1 ON f.FNr = fp1.FNr
          INNER JOIN FIRMA_PROJEKT AS fp2 ON f.FNr = fp2.FNr
          INNER JOIN FIRMA_PROJEKT AS fp3 ON f.FNr = fp3.FNr
          INNER JOIN FIRMA_PROJEKT AS fp4 ON f.FNr = fp4.FNr
          WHERE a.Ort LIKE 'berlin'AND f.Adresse = a.AdrIndex
          AND fp1.ProjektNr =7
          AND fp2.ProjektNr =29
          AND fp3.ProjektNr =90
          AND fp4.ProjektNr =38

          Allerdings wird das Ding bereits bei drei Bezügen sehr langsam, bei vier bekomme ich einen Timeout vom Browser. Eigentlich hätte ich aber fünf Bezüge.

          Kann man das anders lösen, oder irgendwie performanter machen.

          Vielen Dank schon mal !

          1. yo,

            lies doch erst einmal alle hinweise hier genau durch....

            nimm die lösung nixwisser mit den group by und bau sie als unterabfrage ein oder aber benutze meine zweite abfrage, die ich dir gegeben habe. falls es fehler gibt, sprich bevor du dir das leben mit joins schwer machst.

            Ilja

      2. Ich ( bzw. die Besucher meines Portals ) möchten zb. in München alle Kosmetikstudios finden, welche auch Nägel machen, d.h. ProjNr 7 AND ProjNr. 29 .

        Und genau diese Anforderung konnte ich bis dato nicht lösen.

        Gibt es dafür eine Lösung ?

        Also nachdem Ihr lustig die vergangenen 13 Stunden durch den Wald gelaufen seid, ohne die Bäume zu finden, würde mich jetzt doch mal interessieren, was an meinem "arroganten bzw. inkompetenten Blabla" so arrogant bzw. inkompetent war (mal abgesehen davon, dass ich keinen fertigen Code aufgetischt habe).

        1. Ich ( bzw. die Besucher meines Portals ) möchten zb. in München alle Kosmetikstudios finden, welche auch Nägel machen, d.h. ProjNr 7 AND ProjNr. 29 .

          Und genau diese Anforderung konnte ich bis dato nicht lösen.

          Gibt es dafür eine Lösung ?

          Also nachdem Ihr lustig die vergangenen 13 Stunden durch den Wald gelaufen seid, ohne die Bäume zu finden,

          Hast Du verstanden, was der will? Was soll das mit den Kosmetikstudios und Nägelfabrikanten? Das sind Branchen. Da geht man auf die Tabelle "Firmen" und hat die Daten, bzw. hätte die Daten, wenn die Branche eingetragen wäre. Stattdessen wird hier mit Projekten hantiert, dazu eine "n:m"-Beziehung mit eigener Tabelle. Alles schön und gut, aber um was geht es genau? Wie soll bspw. die Suchmaske aussehen? (Idee: Branchen können als checkboxen ausgewählt werden, dazu eine PLZ oder ein PLZ-Bereich eingetragen werden - aber das ist mir alles zu spekulativ)

          1. Hast Du verstanden, was der will? Was soll das mit den Kosmetikstudios und Nägelfabrikanten?

            Ich bin mir nicht so sicher, ob er Nägel fabrizieren will, aber ich bin mir ziemlich sicher, dass

            select firma from firmaprodukt where produkt=1 or produkt=2 group by firma having count(firma)=2

            funktioniert (keine Mehrfacheinträge vorausgesetzt).

            1. yo,

              select firma from firmaprodukt where produkt=1 or produkt=2 group by firma having count(firma)=2

              funktioniert (keine Mehrfacheinträge vorausgesetzt).

              sehe ich genauso, auch in deinem beispiel wird der operator OR verwendent. kann nicht erkennen, warum es nicht funktionieren sollte, ausser das man es noch ein wenig schicker als unterabfrage verpacken muss, um alle andere spalten mit auszugeben, bzw. diese in die gruppierung mit aufzunehmen.

              Ilja