stewe: mysql befehl gesucht

Holla!

Ich habe mich etwas in sql eingearbeitet und habe dann gedacht, dass folgender Befehl funktionieren sollte:

SELECT Titel,Untertitel,Id FROM media ORDER BY ( (Titel LIKE '%Suchbegriff1%') + (Titel LIKE '%Suchbegriff2%') ),Titel,Untertitel,Id

Warum klappt das mit dem "+"-Operator nicht?

Folgender Befehl funktioniert (für mich verwirrenderweise)

SELECT Titel,Untertitel,Id FROM media ORDER BY (Titel LIKE '%Suchbegriff1%'),Titel,Untertitel,Id

Hat es etwas mit dem Ablauf der Ausführung des Befehls zu tun?
Gibt es eine Variante, wie man Befehl 1 zum funktionieren bringen kann? Alternative?

Vielen Dank und Gruss

  1. Mahlzeit stewe,

    SELECT Titel,Untertitel,Id FROM media ORDER BY ( (Titel LIKE '%Suchbegriff1%') + (Titel LIKE '%Suchbegriff2%') ),Titel,Untertitel,Id

    Warum klappt das mit dem "+"-Operator nicht?

    Was genau willst Du denn mit dem "+"-Operator erreichen? Im Moment addierst Du zwei Boole'sche Werte ...

    Folgender Befehl funktioniert (für mich verwirrenderweise)

    SELECT Titel,Untertitel,Id FROM media ORDER BY (Titel LIKE '%Suchbegriff1%'),Titel,Untertitel,Id

    Warum verwirrenderweise? Es wird halt erst nach dem Ergebnis des Vergleichs (Titel LIKE '%Suchbegriff%') sortiert und dann noch nach drei Spalten. Die Frage ist jetzt nur, ob TRUE vor FALSE kommt oder umgekehrt - aber das kannst Du ja noch durch Angabe von "ASC" bzw. "DESC" beeinflussen ...

    Gibt es eine Variante, wie man Befehl 1 zum funktionieren bringen kann? Alternative?

    Du solltest vielleicht erst einmal beschreiben, was Du überhaupt vorhast. Nach was soll denn - umgangssprachlich - sortiert werden?

    MfG,
    EKKi

    --
    sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
    1. Warum klappt das mit dem "+"-Operator nicht?

      Was genau willst Du denn mit dem "+"-Operator erreichen? Im Moment addierst Du zwei Boole'sche Werte ...

      Ich hatte zuerst gedacht, dass es mir einen automatischen Typecast auf INT ausführt und dann diesen auch noch mit CAST((Titel LIKE '%Suchbegriff1%') AS INT) explizit eingeführt - ohne Ergebnis.
      Damit ist auch klar: Beim Vorkommen von 'SuchbegriffX' soll der Wert jeweils um 1 erhöht werden

      Warum verwirrenderweise?

      Mich verwirrt dies, weil der Teil funktioniert, aber in Kombination mit dem + Operator nicht

      aber das kannst Du ja noch durch Angabe von "ASC" bzw. "DESC" beeinflussen ...

      Ist mir klar

      Gibt es eine Variante, wie man Befehl 1 zum funktionieren bringen kann? Alternative?

      Ich will nach der Anzahl der Suchtreffer sortieren - hatte gedacht das wär ausm Kontext leicht zu ersehn :)

      gruss

      1. Mahlzeit stewe,

        Ich hatte zuerst gedacht, dass es mir einen automatischen Typecast auf INT ausführt und dann diesen auch noch mit CAST((Titel LIKE '%Suchbegriff1%') AS INT) explizit eingeführt - ohne Ergebnis.

        Und wieso bist Du der Meinung, dass der arithmetische Operator zur Addition ein solches Verhalten zeigen sollte?

        Warum verwirrenderweise?
        Mich verwirrt dies, weil der Teil funktioniert, aber in Kombination mit dem + Operator nicht

        Vielleicht liegt das daran, dass der "+"-Operator einfach nur falsch angewendet wurde? Überlege Dir genau, was ein Vergleich wie (Titel LIKE '%Suchbegriff1%') zurückgibt. Und dann überlege Dir, was Du mit dieser Information anfangen kannst.

        Ich will nach der Anzahl der Suchtreffer sortieren - hatte gedacht das wär ausm Kontext leicht zu ersehn :)

        Nicht wirklich ... versuche doch erstmal, die Anzahl der jeweiligen Suchtreffer zu ermitteln und Dir als (berechnete) Spalte ausgeben zu lassen.

        MfG,
        EKKi

        --
        sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
        1. Salute Ekki!

          Ich bitte dich, in Zukunft deine Antworten weniger belehrend und etwas mehr auf den Punkt zu bringen. Es wird die Nerven der Fragestellenden schonen - und genauso auch deine (du hast bestimmt auch schon gehässige Antworten gekriegt?). Es ist mir klar, dass du den Background eines Fragestellenden nicht kennen kannst - aber man kann sich bei bestimmten Typen von Antworten schon etwas verarscht vorkommen...:

          Ich hatte zuerst gedacht, dass es mir einen automatischen Typecast auf INT ausführt und dann diesen auch noch mit CAST((Titel LIKE '%Suchbegriff1%') AS INT) explizit eingeführt - ohne Ergebnis.

          Und wieso bist Du der Meinung, dass der arithmetische Operator zur Addition ein solches Verhalten zeigen sollte?

          Was denkst du, wenn du einen Link geschickt bekommst mit nem Anker auf eine Zeile, die dir erklärt, dass man in MySql für die Addition ein "+" zwischen zwei Werte schreibt und dass 3+5=8 ist?...

          Vielleicht liegt das daran, dass der "+"-Operator einfach nur falsch angewendet wurde? Überlege Dir genau, was ein Vergleich wie (Titel LIKE '%Suchbegriff1%') zurückgibt. Und dann überlege Dir, was Du mit dieser Information anfangen kannst.

          Wenn du meine Antwort wirklich gelesen hättest, dann hättest du bemerkt, dass ich die Möglichkeit des falschen Typs bereits in Betracht gezogen habe, mir also klar ist, dass es sich bei der Rückgabe um zwei Booleans handelt und ich diese eigentlich nicht addieren kann. Der Gedanke, dass beim Versuch zwei Booleans zu addieren, diese automatisch in Integer getypecastet werden ist nicht abwegig, dafür gibt es x Beispiele an anderen Orten. Ich bin MySql-Neuling und ja-ich habe noch nicht die ganze Dokumentation durchgelesen. Du als MySql-Kenner hättest dann auch gleich den logischen Schluss gemacht, dass wohl was bei meinem Typecast schief gelaufen sein muss. Und da ich diesen ja sogar explizit notiert habe, hättest du auch gleich gesehn, dass der natürlich nicht funktionieren kann, weils den Typ "INT" nicht gibt. Was wär ne coole Antwort gewesen?
          -> "Ne, der Typecast läuft nicht automatisch.
          Und
          -> Den Typ "INT" gibts nicht in MySQL, entweder nimmst du "SIGNED" oder "UNSIGNED"
          Und Basta. Problem gelöst.

          Ich hab jetzt selbst aus dem groben Kontext deiner Antwort darauf zurückgeschlossen, dass die Berechnung im ORDER BY eigentlich möglich sein müsste und ich entsprechend beim Typecast nen Fehler gemacht haben muss, den ich dann mit etwas Recherche auch gefunden habe.

          Ich meine, den Willen dass man helfen will in Ehren, aber wer helfen will, der sollte sich auch Gedanken darüber machen wie man hilft.
          Das ist wie mit dem Erstellen einer Website. Der Wille in allen Ehren - aber das Wie sollte immer auch diskutiert werden. Auch ein Grund, warum ich dieses Forum ansonsten sehr schätze.

          Gruss und gerne wieder einmal

          stewe

          1. Mahlzeit stewe,

            Was denkst du, wenn du einen Link geschickt bekommst mit nem Anker auf eine Zeile, die dir erklärt, dass man in MySql für die Addition ein "+" zwischen zwei Werte schreibt und dass 3+5=8 ist?...

            Dann denke ich, dass dieser Operator für die Addition von numerischen Werten geeignet ist. Ich denke dann insbesondere *nicht*, dass er sich zur Addition von Boole'schen Werten eignet.

            Wenn du meine Antwort wirklich gelesen hättest, dann hättest du bemerkt, dass ich die Möglichkeit des falschen Typs bereits in Betracht gezogen habe, mir also klar ist, dass es sich bei der Rückgabe um zwei Booleans handelt und ich diese eigentlich nicht addieren kann.

            Aha. Und wieso versuchst Du es trotzdem? Was erwartest Du denn bei der Addition von - sagen wir mal - TRUE und FALSE? Was genau soll da bitte Sinnvolles herauskommen?

            Der Gedanke, dass beim Versuch zwei Booleans zu addieren, diese automatisch in Integer getypecastet werden ist nicht abwegig, dafür gibt es x Beispiele an anderen Orten.

            Dann nenne mir mindestens eins davon - und ich erkläre Dir gerne anschließend, warum die entsprechende Sprache Müll ist. Automatische Typumwandlung ist IMHO generell Müll ... ich habe mit den sich daraus ergebenden Problemen tagtäglich zu kämpfen.

            dass wohl was bei meinem Typecast schief gelaufen sein muss.

            Das hat weniger mit dem Typecast an sich zu tun, sondern eher mit Deiner Erwartung, dass ein solcher automagisch stattfindet. Daher solltest Du eher Dein generelles Vorgehen überdenken und Deine Abfrage neu aufbauen und dabei darauf achten, dass die Datentypen sauber verwendet werden.

            -> Den Typ "INT" gibts nicht in MySQL, entweder nimmst du "SIGNED" oder "UNSIGNED"

            Wieso sollte ich das behaupten, wenn es doch nicht stimmt?

            MfG,
            EKKi

            --
            sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
            1. Salut!

              Dann denke ich, dass dieser Operator für die Addition von numerischen Werten geeignet ist. Ich denke dann insbesondere *nicht*, dass er sich zur Addition von Boole'schen Werten eignet.

              Ne, da fühlt man sich verarscht. Solche Dinge verstehen sich von selbst.

              Aha. Und wieso versuchst Du es trotzdem? Was erwartest Du denn bei der Addition von - sagen wir mal - TRUE und FALSE? Was genau soll da bitte Sinnvolles herauskommen?

              true und false werden weit herum auch als "gesetzt" und "nicht gesetzt", "High" und "low", sowie auch "1" und "0" bezeichnet (je nach Definition - ich komm aus der Elektrotechnik). Automatische Typecasts funktionieren üblicherweise so, dass ein für die gewünschte Operation geeigneter Datentyp gewählt wird. im Falle einer mathematischen Operation mit Booleans ist dabei die Verwendung von "0" und "1" die ziemlich einzig logische und damit ziemlich eindeutige Variante. true+false wäre dann also gleich 1+0=1.
              Warum stellst du mir diese Frage - Ich denke du konntest meine Antwort absehn.

              Dann nenne mir mindestens eins davon

              PHP pflegt einen sehr offenen Umgang mit Datentypen. Daher wohl auch mein Gedanke - Ich nutze MySql zusammen mit PHP.

              • und ich erkläre Dir gerne anschließend, warum die entsprechende Sprache Müll ist. Automatische Typumwandlung ist IMHO generell Müll ... ich habe mit den sich daraus ergebenden Problemen tagtäglich zu kämpfen.

              Kann ich nicht nachvollziehn - gerne höre ich dazu deine Erläuterung. Mein Standpunkt wäre: Gibts keine automatische Typecasts, muss ich diese explizit angeben. Gibts automatische Typecasts und ich habe trotzdem meine eigenen expliziten Typecasts wie ich sie will angegeben, dann kratzen mich die automatischen nicht weiter. Wenn ich aber weis, wo automatische Typecasts möglich sind und wie sie ablaufen, hab ich weniger (wenn auch nur geringfügig) Programmieraufwand.

              Das hat weniger mit dem Typecast an sich zu tun, sondern eher mit Deiner Erwartung, dass ein solcher automagisch stattfindet.

              War das "automaGisch" beabsichtigt? :) haha

              Die Erwartung war eine Fehlschuss, hab ich ja akzeptiert und stört mich nicht weiter. Eigentlich finde auch ich es angenehmer, wenn ich explizit mit bestimmten Datentypen und Typecasts schaffen muss - Das sorgt für Klarheit, die bspw. bei PHP in dieser Hinsicht etwas abgeht.

              Ich werd den Eindruck nicht los, dass du dich ständig auf mein erstes Posting beziehst, wo ich (da ich mir über den Ursprung des Fehlers unklar war, weils bei mir sowohl ohne wie auch mit - aber eben falschem - Typecast nicht funktioniert hatte) den Typecast weggelassen habe im MySql Query.

              Daher solltest Du eher Dein generelles Vorgehen überdenken und Deine Abfrage neu aufbauen und dabei darauf achten, dass die Datentypen sauber verwendet werden.

              Mit dem richtigen Typecast funktionierts jetzt - oder sprichst du noch weitere Probleme im Zusammenhang mit diesem Aufbau an, die sich nicht in Fehlern manifestieren? Performance? NULL-Cases greife ich mit IFNULL ab und das fertige Statement wird mit weiteren Bedingungen ziemlich komplex und lang.

              Wieso sollte ich das behaupten, wenn es doch nicht stimmt?

              Die Aussage bezieht sich natürlich auf die Funktion CAST, ich habe mich unpräzise ausgedrückt. Daher rührt ja auch mein ursprünglicher Fehler beim Typecast - Ich habe mir die Definition der Funktion nicht genügend genau angeschaut, sondern nur das "as type" gesehn und dann entsprechend "INT" eingesetzt.

              Gruss

              stewe

              1. Mahlzeit stewe,

                Dann denke ich, dass dieser Operator für die Addition von numerischen Werten geeignet ist. Ich denke dann insbesondere *nicht*, dass er sich zur Addition von Boole'schen Werten eignet.
                Ne, da fühlt man sich verarscht. Solche Dinge verstehen sich von selbst.

                Nicht unbedingt. Mathematische Operatoren sind etwas komplett anderes als Boole'sche Operatoren.

                Automatische Typecasts funktionieren üblicherweise so, [...]

                Das ist mir klar, das musst Du mir nicht erklären.

                Warum stellst du mir diese Frage - Ich denke du konntest meine Antwort absehn.

                Sie war rhetorisch gemeint.

                Dann nenne mir mindestens eins davon
                PHP pflegt einen sehr offenen Umgang mit Datentypen. Daher wohl auch mein Gedanke - Ich nutze MySql zusammen mit PHP.

                Eben. Und gerade was Datentypen angeht, war PHP in der Vergangenheit eine ziemliche Katastrophe und ist es auch heute noch.

                "001" und 1 sind nun einmal etwas signifikant Unterschiedliches - und wenn ich zwei Variablen, von denen die eine den einen, die andere den anderen Wert enthält, miteinander vergleiche, dann erwarte ich von einem vernünftigen Compiler/Interpreter (JA, von *beiden*!), dass er mir diesen Vergleich mit einer aussagekräftigen Fehlermeldung um die Ohren haut.

                Dieses nonchalante "wir verzeihen dem unbedarften Anfänger-Frickler mal alle Fehler und reimen uns was höchstwahrscheinlich Passendes zurecht"-Umschiffen derartiger Klippen treibt mich bei diversen Sprachen regelmäßig zur Weißglut ... insbesondere, wenn man bestehenden Code ergänzen, erweitern, verändern oder - ganz fies - debuggen soll.

                Wenn ich aber weis, wo automatische Typecasts möglich sind und wie sie ablaufen, hab ich weniger (wenn auch nur geringfügig) Programmieraufwand.

                ... und weniger Kontrolle über das geschriebene Programm. Na prima. Dann lieber während der Entwicklungszeit etwas mehr Aufwand, dafür ist das Ergebnis dann sauber und es kann nicht zur Laufzeit - z.B. durch Benutzereingaben und gerne mal auftretende fehlende Validierung - zu ausgesprochen unerfreulichen Fehlermeldungen kommen.

                MfG,
                EKKi

                --
                sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
                1. Salute!

                  Nicht unbedingt. Mathematische Operatoren sind etwas komplett anderes als Boole'sche Operatoren.

                  Mhm gut, vielleicht bin ich schon zu vertraut mit der Materie.

                  Das ist mir klar, das musst Du mir nicht erklären.

                  Super, dann gehts Dir mal so, wie mir bei deiner Antwort ;)

                  Sie war rhetorisch gemeint.

                  Dafür bin ich momentan zu müde.

                  Dieses nonchalante "wir verzeihen dem unbedarften Anfänger-Frickler mal alle Fehler und reimen uns was höchstwahrscheinlich Passendes zurecht"-Umschiffen derartiger Klippen treibt mich bei diversen Sprachen regelmäßig zur Weißglut

                  Kann ich absolut nachvollziehen, genauso wie deine weiteren Aussagen. Ich konnte aber bisher immer gut damit leben - Vielleicht komm ich später noch mal in eine Situation, wo es auch mich zur Weissglut treiben wird, hoffen tue ich es nicht.

                  Gruss

                  stewe

  2. Hallo,

    Ich habe mich etwas in sql eingearbeitet und habe dann gedacht, dass folgender Befehl funktionieren sollte:

    SELECT Titel,Untertitel,Id FROM media ORDER BY ( (Titel LIKE '%Suchbegriff1%') + (Titel LIKE '%Suchbegriff2%') ),Titel,Untertitel,Id

    Warum klappt das mit dem "+"-Operator nicht?

    was verstehst Du unter "klappt nicht"?

    Folgender Befehl funktioniert (für mich verwirrenderweise)

    SELECT Titel,Untertitel,Id FROM media ORDER BY (Titel LIKE '%Suchbegriff1%'),Titel,Untertitel,Id

    was verstehst Du unter "funktioniert"

    Hat es etwas mit dem Ablauf der Ausführung des Befehls zu tun?
    Gibt es eine Variante, wie man Befehl 1 zum funktionieren bringen kann? Alternative?

    besonders performant dürfte die Abfrage nicht sein, allein schon wegen des zweifachen

    %suchbegriff%,

    wobei Dir kein Index helfen kann.

    Ich kann Dein Problem jedoch nicht nachvollziehen. Ich erhalte die Ergebnisse, von denen ich erwarte, dass Du sie erwartest.

    Beispiel:

    Ausgangstabelle:

    mysql> SELECT plz FROM tabelle;
    +-------+
    | plz   |
    +-------+
    | 12345 |
    | 09876 |
    | 12222 |
    | 44444 |
    | 44000 |
    +-------+
    5 rows in set (0.01 sec)

    Nun mit ein paar berechneten Spalten:
    a) mit 4: enthält die Spalte plz (mindestens) eine 4
    b) mit 0: enthält die Spalte plz (mindestens) eine 0
    c) mit 4oder0: Wertung: für jeden mindestens einmal gefundenen Suchtext gibt es einen Wertungspunkt.

    SELECT  
        plz,  
        (plz LIKE '%4%') mit4,  
        (plz LIKE '%0%') mit0,  
        ((plz LIKE '%4%') + (plz LIKE '%0%')) mit4oder0  
    FROM  
        tabelle  
    
    

    | plz   | mit4 | mit0 | mit4oder0 |
    +-------+------+------+-----------+
    | 12345 |    1 |    0 |         1 |
    | 09876 |    0 |    1 |         1 |
    | 12222 |    0 |    0 |         0 |
    | 44444 |    1 |    0 |         1 |
    | 44000 |    1 |    1 |         2 |

    Und jetzt nach der Wertungsspalte sortiert.

    SELECT  
        plz,  
        (plz LIKE '%4%') mit4,  
        (plz LIKE '%0%') mit0,  
        ((plz LIKE '%4%') + (plz LIKE '%0%')) mit4oder0  
    FROM  
        tabelle  
    ORDER BY  
        ((plz LIKE '%4%') + (plz LIKE '%0%'));  
    
    

    | plz   | mit4 | mit0 | mit4oder0 |
    +-------+------+------+-----------+
    | 12222 |    0 |    0 |         0 |
    | 12345 |    1 |    0 |         1 |
    | 09876 |    0 |    1 |         1 |
    | 44444 |    1 |    0 |         1 |
    | 44000 |    1 |    1 |         2 |

    5 rows in set (0.00 sec)

    Und ja:

    mysql> SELECT TRUE + FALSE;
    +--------------+
    | TRUE + FALSE |
    +--------------+
    |            1 |
    +--------------+
    1 row in set (0.00 sec)

    mysql> SELECT TRUE + TRUE + TRUE;
    +--------------------+
    | TRUE + TRUE + TRUE |
    +--------------------+
    |                  3 |
    +--------------------+
    1 row in set (0.00 sec)

    mysql> SELECT TRUE + TRUE;
    +-------------+
    | TRUE + TRUE |
    +-------------+
    |           2 |
    +-------------+
    1 row in set (0.00 sec)

    MySQL nutzt TINYINT für BOOLEAN.

    Freundliche Grüße

    Vinzenz

    1. Salut Vinzenz!

      Ich muss mich entschuldigen, ich habe deine Antwort neben dem Gespräch mit Ekki komplett überschaut. Das Problem war ein falscher Typecast von meiner Seite. Vielen Dank aber für den Aufwand den du betrieben hast um mir eine Antwort zu geben!
      Ich hab schon in anderen Postings gesehen, dass du wohl ein ziemlicher MySql-Fachmann zu sein scheinst.

      Darum noch ein Frage: Gibt es eine Möglichkeit, eine Query der folgenden (sehr langsamen) Form bei gleicher Funktionalität zu optimieren?

      SELECT Titel,Untertitel,Reihe,Urheber,Herausgeber,Medienart,stichwortliste.Id  
      FROM medienliste,stichwortliste  
      WHERE medienliste.Id=stichworliste.Id  
      GROUP BY stichwortliste.Id  
      HAVING  
      SUM(Stichwort='schweiz')>=1  
      AND SUM(Stichwort='demografie')>=1  
      ORDER BY  
      IFNULL((Titel = 'schweiz demografie'),0) DESC,  
      IFNULL((Untertitel = 'schweiz demografie'),0) DESC,  
      IFNULL((Reihe = 'schweiz demografie'),0) DESC,  
      IFNULL(CAST(Titel LIKE '%schweiz%' AS UNSIGNED) + CAST(Titel LIKE '%demografie%' AS UNSIGNED),0) DESC,  
      IFNULL(CAST(Untertitel LIKE '%schweiz%' AS UNSIGNED) + CAST(Untertitel LIKE '%demografie%' AS UNSIGNED),0) DESC,  
      IFNULL(CAST(Reihe LIKE '%schweiz%' AS UNSIGNED) + CAST(Reihe LIKE '%demografie%' AS UNSIGNED),0) DESC,  
      Titel,Untertitel  
      LIMIT 0,10  
      
      

      Ansonsten muss ich mir dann überlegen, bestimmte Kriterien wegzulassen...

      Wie du vermutlich erraten kannst, handelt es sich um eine Suchabfrage in einer Bibliothekdatenbank, die gleichzeitig die Resultate nach einer bestimmten Priorität ordnet, in diesem Falle mit den Suchbegriffen "schweiz" und "demografie".  Gibts eine Möglichkeit? -SQL ist wie schon ausgeführt neu für mich, ich habe grundsätzlich einfach die Befehle die ich benötigt habe zusammengesucht und zusammengesetzt, ohne Wissen über Performance der Datenbank oder ähnliches.

      es handelt sich um 2 Tabellen:
      medienlist mit spalten (titel,untertitel,reihe,id,etc)
      und der stichwortliste mit spalten (id,stichwort)

      gruss

      stewe

      1. Hallo,

        Ich muss mich entschuldigen, ich habe deine Antwort neben dem Gespräch mit Ekki komplett überschaut.

        sowas kommt vor. Es gibt schlimmeres.

        Das Problem war ein falscher Typecast von meiner Seite.

        Mein Beitrag sollte Dir eigentlich sagen, dass ein CAST im SQL-Dialekt von MySQL gar nicht notwendig ist.

        Vielen Dank aber für den Aufwand den du betrieben hast um mir eine Antwort zu geben!

        Darum noch ein Frage: Gibt es eine Möglichkeit, eine Query der folgenden (sehr langsamen) Form bei gleicher Funktionalität zu optimieren?

        SELECT Titel,Untertitel,Reihe,Urheber,Herausgeber,Medienart,stichwortliste.Id

        FROM medienliste,stichwortliste
        WHERE medienliste.Id=stichworliste.Id
        GROUP BY stichwortliste.Id
        HAVING
        SUM(Stichwort='schweiz')>=1
        AND SUM(Stichwort='demografie')>=1
        ORDER BY
        IFNULL((Titel = 'schweiz demografie'),0) DESC,
        IFNULL((Untertitel = 'schweiz demografie'),0) DESC,
        IFNULL((Reihe = 'schweiz demografie'),0) DESC,
        IFNULL(CAST(Titel LIKE '%schweiz%' AS UNSIGNED) + CAST(Titel LIKE '%demografie%' AS UNSIGNED),0) DESC,
        IFNULL(CAST(Untertitel LIKE '%schweiz%' AS UNSIGNED) + CAST(Untertitel LIKE '%demografie%' AS UNSIGNED),0) DESC,
        IFNULL(CAST(Reihe LIKE '%schweiz%' AS UNSIGNED) + CAST(Reihe LIKE '%demografie%' AS UNSIGNED),0) DESC,
        Titel,Untertitel
        LIMIT 0,10

          
        ich schreibe mal (für mich) übersichtlicher mit expliziter Join-Syntax und verzichte auf das Sortieren und Limitieren der Ergebnismenge.  
          
        ~~~sql
        SELECT  
            m.Titel,  
            m.Untertitel,  
            m.Reihe,  
            m.Urheber,  
            m.Herausgeber,  
            m.Medienart,  
            s.Id,  
        FROM  
            medienliste m  
        INNER JOIN  
            stichwortliste s  
        ON  
            m.Id = s.Id  
        GROUP BY  
            s.Id  
        HAVING  
            SUM(s.Stichwort='schweiz') >= 1  
            AND SUM(s.Stichwort='demografie') >= 1  
        
        

        a) allein das ist schon teuer, weil HAVING erst auf die gesamte Ergebnismenge angewandt wird und nicht vorher einschränkend wirken kann.

        b) Bist Du Dir ganz sicher, dass die Werte in den Spalten

        - Titel,
          - Untertitel,
          - Reihe,
          - Urheber,
          - Herausgeber,
          - Medienart

        zu gleicher Id in der Tabelle stichwortliste alle gleich sind?
        Wenn nein, liefert diese Abfrage in den von mir genannten Spalten nicht vorhersagbare Werte. Ich glaube kaum, dass Du an nicht vorhersagbaren Werten interessiert bist, wenn Du anschließend nach deren Inhalten sortieren willst.

        GROUP BY und nicht aggregierte Spalten, eines meiner Lieblingsthemen.

        Momentan wäre es daher hilfreich, ein paar Datensätze beider Tabellen zur Verfügung zu haben, um das Verhalten nachvollziehen zu können und zielführende Hinweise geben zu können.

        Berechnete Spalten für die Sortierung sind teuer und bei Dir müssen sie für alle Datensätze berechnet werden, weil Du die Anzahl der Datensätze nicht durch eine "echte" WHERE-Klausel einschränkst. Deine WHERE-Klausel ist nur ein implizite Join-Schreibweise. Kann man zuerst die Datensatzanzahl einschränken, die betrachtet werden muss und nur für diese die berechneten Spalten berechnen lassen, so kann dies deutlichen Performancegewinn bringen. Wichtig sind natürlich auch die Indexe und die Frage, ob sie verwendet werden (können). Das und vieles andere sagt Dir EXPLAIN.

        Freundliche Grüße

        Vinzenz

        1. Salut!

          Mein Beitrag sollte Dir eigentlich sagen, dass ein CAST im SQL-Dialekt von MySQL gar nicht notwendig ist.

          Hmm und äh und *die Augen reib*.(Ich hatte den Beitrag vorher nur überflogen) Ich hab das CAST Statement noch mal aus dem Code rausgenommen - und siehe da: Genau wie du sagst (surprise :) ), funktioniert genauso.. Ich würd ja gerne wissen was ich da ursprünglich verknorzt hatte - denn ausprobiert hab ichs mehrfach... problemblind? Hmm. Auf jeden Fall eine schöne Sache, so sieht der Code fürs Auge schon mal angenehmer aus. (hoffentlich hat Ekki deinen Post auch gelesen :) )

          a) allein das ist schon teuer, weil HAVING erst auf die gesamte Ergebnismenge angewandt wird und nicht vorher einschränkend wirken kann.

          Ja das hab ich mir gedacht. Bei nur einem Suchbegriff kann ich diesen mit WHERE realisieren (mache ich in dem Falle also auch), aber bei mehreren schliessen sich die Suchergebnisse natürlich gegenseitig aus und bspw. eine OR Verknüpfung führt nicht zum selben Resultat..

          b) Bist Du Dir ganz sicher, dass die Werte in den Spalten
          (...)
          zu gleicher Id in der Tabelle stichwortliste alle gleich sind?

          Ja. Die Medienliste ist eine reine Auflistung aller vorhandenen Medien mit deren Eigenschaften als Spalten. id<=>medium ist dabei eine 1:1 Beziehung, eine Id ist also eindeutig für ein einziges Medium und damit auch für jeden zugehörigen Spaltenwert.

          also zB:

          ID  |  Titel            | Untertitel                            | ...
          -------------------------------------------------------------------------
          12  | Der bla von bla   | Kolumbus und die Entdeckung Amerikas
          234 | SQL verstehen     | Aufbau, Syntax & Funktionsweise

          ... etc

          Dies im Gegensatz zur stichwortliste, wo beliebig viele Einträge mit einer bestimmten id und einem zugehörigen Stichwort stehen können

          ID  |  Stichwort
          --------------------------
          12  |  bla
          12  |  von
          12  |  Kolumbus
          12  |  Amerikas
          234 |  SQL
          234 |  verstehen
          234 |  Aufbau

          ... etc

          Wenn nein, liefert diese Abfrage in den von mir genannten Spalten nicht vorhersagbare Werte.

          Diesen "Stolperstein" muss ich mir merken. Welchen Wert wählt mysql denn aus in einem solchen Fall? Oder geht das zu tief in die interne Funktionsweise rein? (Auch ein auf den ersten Blick chaotisches Verhalten muss schliesslich, wenn auf rein logischen Vorgängen/Beziehungen beruhend ein vorhersagbares Resultat haben (ausser wenns dann timevariant ist :) ))

          Momentan wäre es daher hilfreich, ein paar Datensätze beider Tabellen zur Verfügung zu haben, um das Verhalten nachvollziehen zu können und zielführende Hinweise geben zu können.

          Reicht dir das obige Beispiel? Was hältst du vom allgemeinen Aufbau der Datenbank? (Dieser ist mir zwar grundsätzlich vorgegeben, ich könnte höchstens Anregungen weiterleiten)

          Berechnete Spalten für die Sortierung sind teuer und bei Dir müssen sie für alle Datensätze berechnet werden, weil Du die Anzahl der Datensätze nicht durch eine "echte" WHERE-Klausel einschränkst. Deine WHERE-Klausel ist nur ein implizite Join-Schreibweise. Kann man zuerst die Datensatzanzahl einschränken, die betrachtet werden muss und nur für diese die berechneten Spalten berechnen lassen, so kann dies deutlichen Performancegewinn bringen.

          Ich berechne vorher noch mit PHP die Gesamtanzahl der Resultate (natürlich ohne Sortierung). Bei dieser Gelegenheit könnte ich die Id-Werte der Resultate abspeichern und dann für die eigentliche Resultatabfrage verwenden, zB mit einem riesigen IN() Statement - Wäre dieses trotz dessen Grösse allenfalls schneller?

          Freundliche Grüsse

          stewe

          1. Hallo stewe,

            ID  |  Titel            | Untertitel                            | ...

            12  | Der bla von bla   | Kolumbus und die Entdeckung Amerikas
            234 | SQL verstehen     | Aufbau, Syntax & Funktionsweise

            Dies im Gegensatz zur stichwortliste, wo beliebig viele Einträge mit einer bestimmten id und einem zugehörigen Stichwort stehen können

            ID  |  Stichwort

            12  |  bla
            12  |  von
            12  |  Kolumbus
            12  |  Amerikas
            234 |  SQL
            234 |  verstehen
            234 |  Aufbau

            den unsortierten Teil Deiner Abfrage kannst Du umschreiben zu

            SELECT DISTINCT  
                m.Titel,  
                -- weitere Spalten  
                s.Id  
            FROM  
                medienliste m  
            INNER JOIN  
                stichwortliste s  
            ON  
                m.Id=s.Id  
            WHERE  
                s.Stichwort IN ('schweiz', 'demografie')  
            
            

            Du solltest sofort erkennen, wie Du die Erweiterung um zusätzliche Stichwörter vornehmen kannst. Außerdem sollte dies schon mal einen Performanceschub geben, weil

            • die Gruppierung entfällt,
            • bereits die WHERE-Klausel zur Einschränkung der Ergebnismenge genutzt wird,
            • die Aggregatsfunktionen nicht berechnet werden müssen.

            . Befrage EXPLAIN, welche Indexe genutzt werden.

            Da Du jedes Medium nur einmal haben willst, aber alle Datensätze zu einem Medium eh die gleichen Werte in allen Spalten aufweisen, kannst Du das Schlüsselwort DISTINCT nutzen, um nur einen Datensatz je Medium zu erhalten.

            Warum verwendest Du in Deiner ORDER-BY-Klausel überall die Funktion IFNULL()?
            Gibt es Medien ohne Titel? Ohne Untertitel kann ich mir vorstellen. Hier könnte die leere Zeichenkette als Standardwert in diesen Spalten helfen, falls die NULL-Werte nicht eine besondere Bedeutung tragen.

            Reicht dir das obige Beispiel? Was hältst du vom allgemeinen Aufbau der Datenbank? (Dieser ist mir zwar grundsätzlich vorgegeben, ich könnte höchstens Anregungen weiterleiten)

            Die Stichwortliste enthält Redundanzen, vermutlich aus Performancegründen.
            Stichworte zu Medien ist eine typische n:m-Beziehung, die normalerweise über eine Zuordnungstabelle abgebildet wird.

            Sonst noch: Hast Du Dir schon einmal die Volltextsuche angeschaut?

            Ich berechne vorher noch mit PHP die Gesamtanzahl der Resultate (natürlich ohne Sortierung).

            Nutze doch FOUND_ROWS() in Verbindung mit SQL_CALC_FOUND_ROWS.

            Freundliche Grüße

            Vinzenz

            1. Hallo Ingrid,

              Du warst nicht mehr wach :-)

              Stewe will nur solche Medien, denen beide Stichworte zugeordnet sind.
              Dein Statement gibt aber alle Medien aus, denen mindestens eines der Stichworte zugeordnet ist.

              SELECT DISTINCT

              m.Titel,
                  -- weitere Spalten
                  s.Id
              FROM
                  medienliste m
              INNER JOIN
                  stichwortliste s
              ON
                  m.Id=s.Id
              WHERE
                  s.Stichwort IN ('schweiz', 'demografie')

                
              Du möchtest lieber meinen Anregungen in [diesem Archivbeitrag](/archiv/2009/1/t182493/#m1207580) folgen.  
                
                
              Freundliche Grüße  
                
              Vinzenz
              
              1. Hola Vinzenz!

                Hallo Ingrid,

                Du warst nicht mehr wach :-)

                Gibt es Vinzenz Mai mehrfach? :)

                Stewe will nur solche Medien, denen beide Stichworte zugeordnet sind.
                Dein Statement gibt aber alle Medien aus, denen mindestens eines der Stichworte zugeordnet ist.

                richtig.

                Du möchtest lieber meinen Anregungen in diesem Archivbeitrag folgen.

                Ich sehe nicht direkt die Relevanz für mein Problem.
                Ich hatte mir auch schon überlegt, etwas mit COUNT(*) zu machen, aber da habe ich das Problem, dass der Datensatz in der Tabelle "begriff" extrem unschön ist (Stichwörter kommen für das gleiche Medium teilweise mehrfach vor)

                Gruss

                stewe

            2. Hola!

              Gibt es Medien ohne Titel? Ohne Untertitel kann ich mir vorstellen.

              Medien ohne Titel gibt es tatsächlich nicht.
              Das IFNULL-Statement kommt aus der automatischen Generierung mittels PHP: Das Ganze ist so programmiert, dass ich die auszulesenden Felder an anderer Stelle einstellen kann, damit ich den Code vielleicht mal wiederverwenden kann... Ich habe allerdings gelesen, dass das IFNULL etwas zeitaufwändig sein soll, überlege mir also wirklich, ob ich dieses für den Titel rausnehmen will.

              Hier könnte die leere Zeichenkette als Standardwert in diesen Spalten helfen, falls die NULL-Werte nicht eine besondere Bedeutung tragen.

              Das tun sie nicht. - Hat es noch einen Einfluss auf die Datenbank, wenn ich den Standard eines Feldes im Nachhinein einstelle oder müsste dies bei Erstellung geschehn? Dann müsste ich dies weiterleiten.

              Die Stichwortliste enthält Redundanzen

              Sie enthält sogar richtig mühsame Redundanzen - sprich, das gleiche Stichwort kommt manchmal für das gleiche Medium mehrmals vor...

              Sonst noch: Hast Du Dir schon einmal die Volltextsuche angeschaut?

              Sehr interessant, dankeschön!

              Gruss

              stewe