Bernd: Keine Ausgabe - komplizierte Abfrage

Hallo,

ich habe ein wenig Probleme mit meinem Script. Wenn ich dieses in phpMyAdmin ausführe erhalte ich keine Einträge, obwohl laut Datenbank welche vorhanden sein müssen und zwar für den heutigen Tag 5

SELECT 
  kp_id, kp_code, kp_userID, kp_status, kt_kalenderID, kt_datum, k_code, k_jobNr, 
  k_bezeichnung, ka_code, ka_titel, ka_farbe 

FROM kalender_personal 
              
LEFT JOIN
  kalender_termine ON kalender_termine.kt_datum = kalender_personal.kp_code

LEFT JOIN
  kalender ON kalender.k_code = kalender_personal.kp_code
              
LEFT JOIN
  kalender_arten ON kalender_arten.ka_code = kalender_personal.kp_code
               
WHERE
  kt_datum = '2019-05-26'

ORDER by test ASC
  1. Tach!

    ich habe ein wenig Probleme mit meinem Script. Wenn ich dieses in phpMyAdmin ausführe erhalte ich keine Einträge, obwohl laut Datenbank welche vorhanden sein müssen und zwar für den heutigen Tag 5

    Ohne die Tabellenstrukturen zu kennen und ohne Testdaten kann ich nur Allgemeines zur Vorgehensweise sagen. Lass zuerst mal das WHERE weg und schau dir an, was überhaupt für eine Datenmenge erzeugt wird. Wenn das keine Erkenntnisse bringt, bau die Query schrittweise auf. Ein Join nach dem anderen hinzufügen und immer die erzeugte Ergebnismenge anschauen.

    dedlfix.

    1. Hallo,

      danke für deine Antwort. Wenn ich das WHERE weg lasse erhalte ich knapp 1.300 Einträge. Kann stimmen. Was mir jetzt auffällt ist, im Feld kt_kalenderID, kt_datum, ka_code, ka_titel und ka_farbe steht NULL.

      Zum Verständnis, ich möchte alle User auslesen, die für ein bestimmtes Datum eingetragen sind.

      Die Tabelle sehen wie folgt aus

      CREATE TABLE IF NOT EXISTS `kalender_personal` (
        `kp_id` int(11) NOT NULL AUTO_INCREMENT,
        `kp_code` varchar(100) NOT NULL,
        `kp_userID` varchar(100) NOT NULL,
        `kp_positionID` varchar(100) NOT NULL,
        `kp_status` varchar(1) NOT NULL DEFAULT '0',
        PRIMARY KEY (`kp_id`)
      ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1805 ;
      
      CREATE TABLE IF NOT EXISTS `kalender_termine` (
        `kt_id` int(11) NOT NULL AUTO_INCREMENT,
        `kt_kalenderID` varchar(200) NOT NULL,
        `kt_datum` date NOT NULL,
        `test` int(10) NOT NULL,
        PRIMARY KEY (`kt_id`)
      ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=12261 ;
      
      CREATE TABLE IF NOT EXISTS `kalender` (
        `k_id` int(11) NOT NULL AUTO_INCREMENT,
        `k_code` varchar(200) NOT NULL,
        `k_art` varchar(200) NOT NULL,
        `k_jobNr` varchar(100) NOT NULL,
        `k_bezeichnung` varchar(200) NOT NULL,
        `k_grund` text NOT NULL,
        `k_farbe` varchar(200) NOT NULL,
        `k_datum_von` date NOT NULL,
        `k_datum_bis` date NOT NULL,
        PRIMARY KEY (`k_id`)
      ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1136 ;
      
      CREATE TABLE IF NOT EXISTS `kalender_arten` (
        `ka_id` int(11) NOT NULL AUTO_INCREMENT,
        `ka_code` varchar(200) NOT NULL,
        `ka_titel` varchar(200) NOT NULL,
        `ka_farbe` varchar(200) NOT NULL,
        PRIMARY KEY (`ka_id`)
      ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=10 ;
      
      1. Tach!

        danke für deine Antwort. Wenn ich das WHERE weg lasse erhalte ich knapp 1.300 Einträge. Kann stimmen. Was mir jetzt auffällt ist, im Feld kt_kalenderID, kt_datum, ka_code, ka_titel und ka_farbe steht NULL.

        Warum bei einem Left Join NULL entstehen kann, wenn kein NULL in den Daten steht, ist Basiswissen.

        dedlfix.

        1. OK, ich habe die Abfrage etwas umgebaut

          SELECT 
            kt_kalenderID, kt_datum, kp_id, kp_code, kp_userID, k_code, k_jobNr, k_bezeichnung,
            per_anrede, per_name, per_vorname 
          
          FROM kalender_termine
                        
          LEFT JOIN
            kalender ON kalender.k_code = kalender_termine.kt_kalenderID
          
          LEFT JOIN
            kalender_personal ON kalender_personal.kp_code = kalender_termine.kt_kalenderID
          
          LEFT JOIN
            personal ON personal.per_code = kalender_personal.kp_userID
                         
          WHERE
            kt_datum = '2019-05-26'
          
          AND kp_userID != ""
          
          ORDER by test ASC
          

          Jetzt erhalte ich auch eine Ausgabe

          Zeige Datensätze 0 - 10 ( 11 insgesamt, Die Abfrage dauerte 0.0035 Sekunden)

          Scheinbar muss ich eine ganz bestimmte Reihenfolge einhalten wenn ich mit einem Datum arbeite?

          1. Tach!

            Scheinbar muss ich eine ganz bestimmte Reihenfolge einhalten wenn ich mit einem Datum arbeite?

            Das hat nichts mit bestimmten Datentypen zu tun, sondern mit Mengenlehre. Wenn du zwei Mengen miteinander verbindest und dabei entsteht kein Ergebnis, kann auch keins mehr entstehen, wenn du noch eine Menge hinzufügst, die keinen Anknüpfungspunkt in der leeren Menge finden kann.

            Deswegen empfahl ich ja das schrittweise Vorgehen, damit du siehst, was da jeweils entsteht.

            dedlfix.

      2. Wenn Du NULL kriegst, kann das auch daran liegen daß Dein JOIN falschherumrum (seitenverkehrt) ist. Also mach entweder einen right Join oder nimm die Tabelle kalender_termine als Basistabelle, denn hier ist das feld kt_datum.

        SELECT .. FROM kalender_termine
        JOIN kalender_arten usw. 
        WHERE kt_datum = '..'
        

        Und zur Optimierung lege einen Index auf kt_datum. Bei Deinen paar Daten ist er noch nicht nötig, aber das wird noch kommen. MFG

        Und arbeite mit aussagekräftigen Alias'n bei Deinen Abfragen!

        1. Hallo,

          SELECT .. FROM kalender_termine
          JOIN kalender_arten usw. 
          WHERE kt_datum = '..'
          

          das habe ich gestern bereits gemacht:
          https://forum.selfhtml.org/self/2019/may/26/keine-ausgabe-komplizierte-abfrage/1749400#m1749400

          Ich dachte bis zu diesem Zeitpunkt immer, die Reihenfolge spielt keine Rolle.

          Und arbeite mit aussagekräftigen Alias'n bei Deinen Abfragen!

          Du meinst mit AS? Ich finde persönlich es sehr umständlich jede Spalte umzubenennen.

          1. Hallo,

            SELECT .. FROM kalender_termine
            JOIN kalender_arten usw. 
            WHERE kt_datum = '..'
            

            das habe ich gestern bereits gemacht:
            https://forum.selfhtml.org/self/2019/may/26/keine-ausgabe-komplizierte-abfrage/1749400#m1749400

            Ich dachte bis zu diesem Zeitpunkt immer, die Reihenfolge spielt keine Rolle.

            Die Reihenfolge bestimmt ja ob es ein LEFT oder RIGHT Join wird.

            Und arbeite mit aussagekräftigen Alias'n bei Deinen Abfragen!

            Du meinst mit AS? Ich finde persönlich es sehr umständlich jede Spalte umzubenennen.

            Ja, AS bzw. Alias. Es geht ja nicht um das Umbebennen schlechthin sondern um die Weiterverarbeitung! So kann man z.B. die Aliase auf die Schlüssel einer Templating Engine anpassen und dies auch umgekehrt. Wenn das Template bereits steht und der Kollege sagt da muss Vorname rein dann wird einfach nur ein Alias entsprechend gesetzt und nicht das ganze Template geändert. MFG

            1. Tach!

              SELECT .. FROM kalender_termine
              JOIN kalender_arten usw. 
              WHERE kt_datum = '..'
              

              das habe ich gestern bereits gemacht:
              https://forum.selfhtml.org/self/2019/may/26/keine-ausgabe-komplizierte-abfrage/1749400#m1749400

              Ich dachte bis zu diesem Zeitpunkt immer, die Reihenfolge spielt keine Rolle.

              Die Reihenfolge bestimmt ja ob es ein LEFT oder RIGHT Join wird.

              Das ist nach wie vor nicht richtig. Ein Outer Join, ob Left oder Right, benötigt LEFT oder RIGHT als Schlüsselwort, sonst ist es ein Inner Join. Lediglich das Schlüsselwort OUTER kann weggelassen werden.

              Dass es dann immer noch darauf ankommt, was links vom LEFT/RIGHT OUTER JOIN und was rechts steht, ist unbestritten. Das sollte ja auch anhand des Verhaltens klar sein, dass eine davon die Haupttabelle sein muss, deren Datensätze immer in die Ergebnismenge kommen, und die Felder der anderen bei Abwesenheit eines Datensatzes mit Verknüpfungsbedingung zu NULL werden können. Nur das Schlüsselwort LEFT/RIGHT kann nicht wegelassen werden.

              Und arbeite mit aussagekräftigen Alias'n bei Deinen Abfragen!

              Du meinst mit AS? Ich finde persönlich es sehr umständlich jede Spalte umzubenennen.

              Das ist auch nicht notwendig. Wenn du mit deiner Benennung zufrieden bist und du keinen Grund für eine Alias siehst oder es keinen technischen Zwang gibt (gibt es in dem Fall nicht), kannst du das problemlos so lassen.

              Ja, AS bzw. Alias. Es geht ja nicht um das Umbebennen schlechthin sondern um die Weiterverarbeitung! So kann man z.B. die Aliase auf die Schlüssel einer Templating Engine anpassen und dies auch umgekehrt.

              Das kann man auch mit den derzeitigen Bezeichnern.

              Wenn das Template bereits steht und der Kollege sagt da muss Vorname rein dann wird einfach nur ein Alias entsprechend gesetzt und nicht das ganze Template geändert.

              Ja, wenn dann. Es gibt immer Gründe für irgendeine bestimmte Maßnahmen. Nur es als unabdingbar hinzustellen, ist nicht notwendig.

              dedlfix.

          2. PS: Der Alias ist ein wichtiges Instrument zur Trennung von Datenhaltung und Anwendung. Durch eine solche Abstrahierung wird der Datenhaltungslayer transparenter und alles zusammen wartungsfreundlicher. D.h. daß Du per Alias besser mit etwaigen Veränderungen/Skalierungen zurechtkommst, weil tabname.colname eben nicht namentlich in die Anwendung verschleppt wird und wenn da eine Änderung eforderlich wird, bleibt der Alias davon unberührt.

            Darüber hinaus liefern Funktionen z.B. so etwas

            mysql> select count(url) from log;
            +------------+
            | count(url) |
            +------------+
            |       1997 |
            +------------+
            
            
            mysql> select count(url) as cnt from log;
            +------+
            | cnt  |
            +------+
            | 1997 |
            +------+
            

            was die Zweckmäßigkeit eines ALias selbst erklärt. Insgesamt ist die Vergabe von Alias'n eine praktische Angelegenheit die sich in vielen Jahren meiner Programmiertätigkeit immer wieder als sehr nützlich erwiesen hat. MFG

            1. Tach!

              PS: Der Alias ist ein wichtiges Instrument zur Trennung von Datenhaltung und Anwendung. Durch eine solche Abstrahierung wird der Datenhaltungslayer transparenter und alles zusammen wartungsfreundlicher. D.h. daß Du per Alias besser mit etwaigen Veränderungen/Skalierungen zurechtkommst, weil tabname.colname eben nicht namentlich in die Anwendung verschleppt wird und wenn da eine Änderung eforderlich wird, bleibt der Alias davon unberührt.

              Naja. Üblicherweise steht das SQL-Statement im Code direkt vor der Abfrageroutine. Ob man einen Namenswechsel - falls man ihn benötigt - nun per Alias oder im nachfolgenden Code vornimmt, nimmt sich vom Aufwand her nicht viel. Langname und gegebenenfalls Alias stehen also bereits in der Anwendung, weil das Statement darin notiert ist. Welchen Namen man im weiteren Verlauf nehmen möchte, ist eine Frage der Vorliebe. Wenn sich der Feldname in Zukunft ändert, kann man immer noch einen Alias hinzufügen oder ein Umschreiben nach der Abfrage vornehmen. Beides liegt nahe beieinander. Ich sehe die Sache mit dem Alias weniger dramatisch, als du sie hier darstellst. Man kann, aber man muss nicht.

              Pseudocode:

              sql = "SELECT p_name AS name FROM person"
              query(sql)
              records = []
              while ...
                records[] = fetch_array
              end
              return records
              
              sql = "SELECT p_name FROM person"
              query(sql)
              while ...
                record = fetch_array
                records[] = ["name" => record["p_name"]]
              end
              return records
              

              Ja, man spart sich das anschließende Umschreiben, vor allem wenn man es nur wegen der Namensänderung und nicht noch aus anderen Gründen macht. Auf der anderen Seite steht nur ein etwas längeres SQL-Statement. Aber wenn man mit seinem p_name völlig zufrieden ist, braucht man weder Alias noch eine Nachbehandlung, und hat trotzdem eine offene Zukunft mit einer der beiden Varianten.

              dedlfix.

              1. Ich frag mich immer wieder warum PHP es immer noch nicht geschafft hat, korrespondierende Klammern als Stringbegrenzer einzuführen die 1. ermöglichen SQL Statements mehrzeilig und übersichtlich zu schreiben und die 2. jeder gängige Editor als zusammengehörig erkennt.

                1. Hallo pl,

                  Nr. 1 löst PHP mit der HEREDOC/NOWDOC Syntax. Sicher, es gibt schöneres. Aber das Feature "mehrzeilige Strings" ist grundsätzlich da.

                  Nr. 2 ist ein leichtes Problem, man muss dann schon einen EDITOR verwenden, der PHP-Syntax kennt. Das kann nicht jeder, aber viele.

                  Rolf

                  --
                  sumpsi - posui - clusi
                2. Tach!

                  Ich frag mich immer wieder warum PHP es immer noch nicht geschafft hat, korrespondierende Klammern als Stringbegrenzer einzuführen die 1. ermöglichen SQL Statements mehrzeilig und übersichtlich zu schreiben und die 2. jeder gängige Editor als zusammengehörig erkennt.

                  In welchen wichtigen Sprachen werden denn Klammern als Stringbegrenzer verwendet? PHP hat für diesen Zweck die Heredoc- und Nowdoc-Syntax, die auch anderenorts bekannt ist.

                  $text = <<<END
                  Zeile 1
                  Zeile 2
                  END;
                  was_anderes():
                  

                  Kann Notepad++ genau wie Syntaxhervorhebung des Forums problemlos erkennen. Damit sollte auch jeder andere Editor zurechtkommen, der Bash-Unterstützung an Bord hat.

                  dedlfix.

                  1. In welchen wichtigen Sprachen werden denn Klammern als Stringbegrenzer verwendet?

                    in Perl:

                    my $q = q(
                      SELECT 
                        a.name  as Lastname,
                        a.vname as Firstname,
                        k.name  as Konfession
                      FROM
                        address a
                      JOIN 
                        konfession k USING(id)
                      WHERE
                        k.name = "Konfessionslos"
                      ORDER by
                        a.name
                    );
                    

                    Und je nach Geschmack kann man auch [] oder {} als korrespondierende Klammern verwenden, die jeder Editor zuordnen kann, gerade bei längeren Geschichten.

                    MFG

                    1. Tach!

                      In welchen wichtigen Sprachen werden denn Klammern als Stringbegrenzer verwendet?

                      in Perl:

                      Ich frage nach wichtigen Sprachen. 😛

                      Und je nach Geschmack kann man auch [] oder {} als korrespondierende Klammern verwenden, die jeder Editor zuordnen kann, gerade bei längeren Geschichten.

                      Ach, und was ist, wenn nicht nur der Editor sondern auch Perl selbst bei kürzeren Geschichten schon aus dem Tritt kommen?

                      my $q = q(foo ) bar);
                      

                      Jedenfalls hat PHP (und andere Sprachen) sowohl mit Anführungszeichen als auch mit Herdoc/Nowdoc die Möglichkeit, Strings übersichtlich und mehrzeilig zu erstellen.

                      dedlfix.

                      1. hi,

                        Ach, und was ist, wenn nicht nur der Editor sondern auch Perl selbst bei kürzeren Geschichten schon aus dem Tritt kommen?

                        my $q = q(foo ) bar);
                        

                        Wenn hier jemand aus dem Tritt kommt ist das nicht Perl sondern der Programmierer der den Kontext nicht beachtet. my $q = q[foo ) bar]; wäre eine Variante dem gerecht zu werden. Der q-Operator erlaubt es schließlich, die Stringbegrenzerzeichen selbst festzulegen, so daß man auf zusätzliche Maskierungen verzichten kann.

                        MFG

                    2. Hallo pl,

                      in Perl:

                      my $q = q(
                        SELECT 
                          a.name  as Lastname,
                          a.vname as Firstname,
                          k.name  as Konfession
                        FROM
                          address a
                        JOIN 
                          konfession k USING(id)
                        WHERE
                          k.name = "Konfessionslos"
                        ORDER by
                          a.name
                      );
                      

                      in PHP:

                      $q = "  
                        SELECT 
                          a.name  as Lastname,
                          a.vname as Firstname,
                          k.name  as Konfession
                        FROM
                          address a
                        LEFT JOIN
                          konfession k USING(id)
                        WHERE
                          k.name = 'Konfessionslos'
                        ORDER by
                          a.name
                      ";
                      

                      Bis demnächst
                      Matthias

                      --
                      Pantoffeltierchen haben keine Hobbys.
                      ¯\_(ツ)_/¯
                      1. Hallo Matthias,

                        äh, nö? Zumindest bei mir nicht.

                        Update.

                        äh doch. Habe die " nicht in ' konvertiert 😳
                        Aber das zeigt den Vorteil von heredoc/nowdoc: Man kann mit Anführungszeichen um sich schmeißen wie man will.

                        Rolf

                        --
                        sumpsi - posui - clusi
                    3. Hallo pl,

                      $this->q = <<<SQL
                        SELECT 
                          a.name  as Lastname,
                          a.vname as Firstname,
                          k.name  as Konfession
                        FROM
                          address a
                        JOIN 
                          konfession k USING(id)
                        WHERE
                          k.name = "Konfessionslos"
                        ORDER by
                          a.name
                      SQL;
                      

                      geht doch. Ab PHP 7.3 muss das End-SQL auch nicht mehr zwingend auf Stelle 1 stehen. Rücke ich es 4 Stellen ein, werden im heredoc-String pro Zeile die ersten 4 Stellen entfernt.

                      $q = <<<SQL
                               SELECT *
                               FROM foo
                               ORDER BY bar
                              SQL;
                      echo $q;
                      

                      ergibt

                       SELECT *
                       FROM foo
                       ORDER BY bar
                      

                      Rolf

                      --
                      sumpsi - posui - clusi
                      1. hi @Rolf B

                        Das kannste mit Perl auch alles so machen. Macht aber keiner. Das macht höchstens jemand, der den Sinn des q-Operators nicht verstanden hat. Wenn wir schon programmieren dann mit Stil, so muss das aussehen.

                        Und dann wäre noch ein nettes Feature was Perl bietet:

                        # hier steht Code
                        # Zugriff auf die Texte unterhalb des DATA-Token
                        read(DATA, my $text, -s DATA);
                        
                        __DATA__
                        Hier stehen SQL Statments, Texte, Templates usw.
                        

                        Womit man Texte/Templates auch hervorragend vom Code trennen kann. MFG

                    4. In welchen wichtigen Sprachen werden denn Klammern als Stringbegrenzer verwendet?

                      in Perl:

                      my $q = q(
                        SELECT 
                          a.name  as Lastname,
                          a.vname as Firstname,
                          k.name  as Konfession
                        FROM
                          address a
                        JOIN 
                          konfession k USING(id)
                        WHERE
                          k.name = "Konfessionslos"
                        ORDER by
                          a.name
                      );
                      

                      Und je nach Geschmack kann man auch [] oder {} als korrespondierende Klammern verwenden, die jeder Editor zuordnen kann, gerade bei längeren Geschichten.

                      MFG

                      PS: Das Template mit Mustache sähe dann so aus:

                      {{#names}}
                      <tr>
                        <td> {{Lastname}} </td>
                        <td> {{Firstname}} </td>
                        <td> {{Konfession}} </td>
                      </tr>
                      {{/names}}
                      

                      (Table Body) Und die dazugehörige Datenstruktur mit der das gerendert wird, liefert eine einzige Anweisung

                      my $names = $dbh->selectall_arrayref($q, {Slice=>{}});
                      Template::Mustache->render( $tbody, { names => $names} );
                      

                      Von soviel Komfort können PHP Entwickler gar nicht träumen weil sie sowas noch nie gesehen, geschweige denn angewandt haben 😉

                      MFG

                      1. my $names = $dbh->selectall_arrayref($q, {Slice=>{}});
                        Template::Mustache->render( $tbody, { names => $names} );
                        

                        Von soviel Komfort können PHP Entwickler gar nicht träumen weil sie sowas noch nie gesehen, geschweige denn angewandt haben 😉

                        In PHP sähe das etwas kürzer aus:

                        $names = $statement->fetchAll();
                        echo (new Mustache_Engine)->render($tbody, ['names' => $names]);
                        
  2. Hallo Bernd,

    ergänzend zu Dedlfix:

    Welchen Datentyp hat die Spalte kt_datum? Vielleicht hast Du das früher mal geschrieben, aber das merken wir uns nicht unbedingt 😀

    Die LEFT JOINs reduzieren nicht die Ergebnismenge und können darum nicht an den 0 Treffern schuld sein. Es muss der WHERE sein, und ich würde mal vermuten: kt_datum ist ein DATETIME-Wert. In dem Fall musst Du einen Bereich abfragen: kt_datum >= '2019-05-26' AND kt_datum < '2019-05-27'

    Das ist natürlich blöd, wenn das abzufragende Datum aus einer Variablen kommen soll. Was Du aber keinesfalls tun solltest, ist dies:

    SELECT kp_id, kp_code, kp_userID, kp_status, kt_kalenderID, kt_datum, ...
    FROM kalender_personal 
    LEFT JOIN ...
    LEFT JOIN ...
    LEFT JOIN ...
    WHERE  DATE(kt_datum) = '2019-05-26'
    

    Das wird zwar funktionieren, ist aber ineffizient, weil MYSQL dann einen Table Scan macht. Bestenfalls einen Index-Scan (wenn kt_datum im Index ist).

    Besser ist es, in PHP das Datum des Folgetages zu bestimmen und damit die Bereichsabfrage zu bauen.

    Rolf

    --
    sumpsi - posui - clusi
    1. Hallo,

      kt_datum ist ein date Feld. Das Datum wird 2019-05-26 gespeichert. Die Strukturen meiner Tabellen habe ich hier gezeigt:

      https://forum.selfhtml.org/self/2019/may/26/keine-ausgabe-komplizierte-abfrage/1749394#m1749394

      1. Hallo,

        kt_datum ist ein date Feld.

        Die Frage die sich mir hier stellt: lässt sich ein date-Feld (kt_datum) mit einem varchar-Feld (kp_code) joinen? Vermutlich ist die interne Darstellung eine andere und daher unmöglich…

        Gruß
        Kalk

        1. Tach!

          Die Frage die sich mir hier stellt: lässt sich ein date-Feld (kt_datum) mit einem varchar-Feld (kp_code) joinen? Vermutlich ist die interne Darstellung eine andere und daher unmöglich…

          Das ist ein simpler Vergleich, bei dem bei Bedarf eine Typkonvertierung stattfindet. Datumsangaben werden üblicherweise als Stringliteral geschrieben und da gibt es auch kein Problem, so ein Stringliteral mit einem Datum zu vergleichen, wenn das Stringliteral syntaktisch richtig wie ein Datum geschrieben ist.

          dedlfix.

      2. Hallo Bernd,

        mir fällt auf, dass deine umgebaute Query anders joined als die Originalquery.

        alt: kalender_termine.kt_datum = kalender_personal.kp_code
        neu: kalender_personal.kp_code = kalender_termine.kt_kalenderID

        Das wird wohl der Hauptgrund dafür sein, dass Du auf einmal Treffer bekommst.

        Generell solltest Du noch einen EXPLAIN auf deine neue Query machen und Dir merken. Und dann solltest Du

        • den LEFT JOIN mit kalender_personal nach vorn ziehen (weil Du darauf einen WHERE ansetzt)
        • das LEFT in diesem LEFT JOIN weglassen, weil Du kp_code != "" abfragst, was Sätze abweist, in denen kp_code NULL ist. Die Sätze, die Du durch einen LEFT JOIN zusätzlich bekommst, werden demnach vom WHERE gleich wieder weggefressen.

        Also so:

        SELECT 
          kt_kalenderID, kt_datum, kp_id, kp_code, kp_userID, k_code, k_jobNr, k_bezeichnung,
          per_anrede, per_name, per_vorname 
        
        FROM kalender_termine
                      
        JOIN
          kalender_personal ON kalender_personal.kp_code = kalender_termine.kt_kalenderID
        
        LEFT JOIN
          kalender ON kalender.k_code = kalender_termine.kt_kalenderID
        
        LEFT JOIN
          personal ON personal.per_code = kalender_personal.kp_userID
                       
        WHERE
          kt_datum = '2019-05-26'
        
        AND kp_userID != ""
        
        ORDER by test ASC
        

        Du kannst Dich dann auch noch fragen, ob die Beziehung kalender_termine -> kalender tatsächlich optional ist (sprich: ob es kt_kalenderIDs geben kann, zu denen Du keinen k_code findest). Die gleiche Frage wäre für die Beziehung kalender_personal -> personal zu stellen. Wenn die Namen deiner Tabellen gut gewählt sind, würde ich annehmen, dass diese Beziehungen obligatorisch sind. Und dann kann das LEFT da weg.

        Nachdem Du unnötige LEFT entfernt hast, solltest Du nochmal einen EXPLAIN machen und gucken ob der gewählte Zugriff besser geworden ist.

        Ach ja, natürlich sollten die Spalten kp_code, k_code und per_code in einem Index zu finden sein, damit die JOINs nicht zu Table- oder Index-Scans führen. Aber das weißt Du sicherlich schon.

        Rolf

        --
        sumpsi - posui - clusi