Bernd: gesamte Anzahl auslesen

Hallo,

ist es möglich obwohl ich ein LIMIT in einer Abfrage habe, die Gesamtmenge zu bekommen? Meine Funktion schaut derzeit wie folgt aus

function Artikel($mysqli, $code) {
    
        $stmt = $mysqli->prepare("

            SELECT a_id, a_code, a_titel ma_id, ma_titel  
            FROM artikel 
            LEFT JOIN marken ON marken.ma_id = artikel.a_programm 
            WHERE a_katID=? AND a_status = 1 ORDER BY RAND() LIMIT 5");

        $stmt->bind_param("s", $code);
        $stmt->execute();
        $stmt->bind_result($a_id, $a_code, $a_titel $ma_id, $ma_titel);
                
        $stmt->store_result();

            if($stmt->num_rows() >  0) {     
                while ($stmt->fetch()){
                    $Artikel[] = array( 
                        'a_id'                      => $a_id, 
                        'a_code'                    => $a_code,
                        'a_titel'                   => $a_titel,
                        'ma_id'                     => $ma_id,
                        'ma_titel'                  => $ma_titel
                    );
                }

            return $Artikel;
        }
    }
  1. Tach!

    ist es möglich obwohl ich ein LIMIT in einer Abfrage habe, die Gesamtmenge zu bekommen?

    Ja, mit SQL_CAL_FOUND_ROWS und FOUND_ROWS().

    dedlfix.

    1. https://phpperformance.de/server/database/sql_calc_found_rows-oder-wie-man-effektiv-blaetternavigationen-umsetzt

      Danke. Verstehe ich irgendwie nicht. In diesem Artikel wird gesagt, man muss SELECT FOUND_ROWS() direkt nach der LIMIT-Abfrage ausführt.

      function Artikel($mysqli, $code) {
          
              $stmt = $mysqli->prepare("
      
                  SELECT SQL_CALC_FOUND_ROWS, a_id, a_code, a_titel ma_id, ma_titel  
                  FROM artikel 
                  LEFT JOIN marken ON marken.ma_id = artikel.a_programm 
                  WHERE a_katID=? AND a_status = 1 ORDER BY RAND() LIMIT 5");
      
              $stmt->bind_param("s", $code);
              $stmt->execute();
              $stmt->bind_result($a_id, $a_code, $a_titel $ma_id, $ma_titel);
                      
              $stmt->store_result();
      
                  if($stmt->num_rows() >  0) {     
                      while ($stmt->fetch()){
                          $Artikel[] = array( 
                              'a_id'                      => $a_id, 
                              'a_code'                    => $a_code,
                              'a_titel'                   => $a_titel,
                              'ma_id'                     => $ma_id,
                              'ma_titel'                  => $ma_titel
                          );
                      }
      
                  return $Artikel;
              }
          }
      

      Vielleicht ist es doch besser, ich schreibe dazu eine eigene Funktion und lass die andere wie sie war.

      1. Tach!

        https://phpperformance.de/server/database/sql_calc_found_rows-oder-wie-man-effektiv-blaetternavigationen-umsetzt

        Danke. Verstehe ich irgendwie nicht. In diesem Artikel wird gesagt, man muss SELECT FOUND_ROWS() direkt nach der LIMIT-Abfrage ausführt.

        Zum einen, SQL_CALC_FOUND_ROWS ist ein Keyword, kein Spaltenname, dem folgt kein Komma.

        SELECT FOUND_ROWS() ist eine zweite Abfrage, die man separat und ganz normal wie jede andere Query ausführen muss, inklusive Ergebnis-Fetchen, und das gleich im Anschluss nachdem man die Query mit dem SQL_CALC_FOUND_ROWS erledigt hat.

        dedlfix.

        1. Hallo,

          verstehe ich leider nicht. Hab es jetzt so gemacht.

              function ArtikelAnzahl($mysqli, $id){
                  $sql = "SELECT COUNT(*) AS `amount` FROM artikel WHERE a_katID=? AND a_status = 1";
                  $res = $mysqli->prepare($sql);
                  $res->bind_param("s", $id);
                  $res->execute();
                  $res->bind_result($amount);
                  $res->fetch();
                  $res->close();  
          
                  return $amount; 
              }
          
          1. Tach!

            verstehe ich leider nicht.

            Ich verstehe auch nicht, was du nicht verstehst, wenn du mir es nicht sagst, wo es hängt.

            Hab es jetzt so gemacht.

            Wenn du dabei das Statement änderst zu SELECT FOUND_ROWS() und das bind_param weglässt, ist es genau das, was du für SQL_CALC_FOUND_ROWS brauchst (und in dessen Anschluss ausführen musst).

            dedlfix.

      2. Vielleicht ist es doch besser, ich schreibe dazu eine eigene Funktion und lass die andere wie sie war.

        Ja. Die Performance von Abfragen von SQL_CAL_FOUND_ROWS / FOUND_ROWS() lässt gegenüber jenen Lösungen mit zwei Abfragen (Zählen mit where,aber ohne limit + Abfrage mit where und limit) einigen Quellen nach GANZ ARG zu wünschen übrig.

        1. Tach!

          Vielleicht ist es doch besser, ich schreibe dazu eine eigene Funktion und lass die andere wie sie war.

          Ja. Die Performance von Abfragen von SQL_CAL_FOUND_ROWS / FOUND_ROWS() lässt gegenüber jenen Lösungen mit zwei Abfragen (Zählen mit where,aber ohne limit + Abfrage mit where und limit) einigen Quellen nach GANZ ARG zu wünschen übrig.

          Soll das eine generelle Aussage sein oder nur eine zu bestimmten Fällen? Wie soll das außerdem möglich sein? Wenn für SQL_CALC_FOUND_ROWS alle Ergebnisse gezählt und dafür ermittelt werden müssen, so müssen sie das bei einer COUNT(*)-Abfrage genauso.

          Aber abgesehen davon ist SQL_CALC_FOUND_ROWS/FOUND_ROWS() mittlerweile deprecated. - Ah, da steht ja auch die Antwort, SQL_CALC_FOUND_ROWS kann nicht mit denselben Optimierungen wie COUNT(*) arbeiten. Warum auch immer.

          dedlfix.

        2. Hallo ursus,

          als ich das Problem dem Stapelüberlauf meines Vertrauens vorgelegt habe, fand ich heraus, dass es noch schlimmer ist: offenbar ist Oracle von dieser Idee nicht (mehr) überzeugt. Bei MariaDB steht es nicht.

          Keyword und Funktion sind seit MySQL 8.017 missbilligt und auf der Roten Liste. Was die Maria daraus macht, ist natürlich eine andere Frage, aber vermutlich

          Also Bernd: Mach weiter mit COUNT. Ein Index auf a_katId, der ggf. noch a_status an letzter Stelle mit einschließt, dürfte dann zum besten und zukunftssichersten Ergebnis führen.

          Edit: Ach verdammt, das schmökere ich bei MariaDB rum und Dedlfix überholt mich rechts :)

          Rolf

          --
          sumpsi - posui - clusi