I Carsten: MySQL - Blättermenü erstellen - Verständnisproblem

Guten Abend!

Zur (langen) Erklärung, ich habe 2 Tabellen:

tblUsers:                        tblOrders:
| Benutzername | Id |    und    | RNr | UserId | id |
---------------------           ---------------------
| foo          | 1  |           | 1a  | 1      | 1  |
| bar          | 1  |           | 1b  | 1      | 2  |
---------------------           ---------------------

Es besteht eine 1:n Beziehung.
Ein Benutzer kann eine Rechnungsnummer haben, muss aber nicht.
Jeder Rechnungsnummer ist aber genau 1 Kunden zugeordnet.

Ich möchte meine Daten jeweils unter folgenden Bedingungen:
1a. alle Daten aus tblUsers
1b. nur Daten aus tblUsers (+tblOrders) denen Daten aus tblOrders zugeordnet sind

Für 1a brauch ich nur eine Abfrage über die gesamte Tabelle tblUsers.
Für 1b muss ich beide Tabellen ansprechen und wahrscheinlich durchsucht die Datenbank auch beide Tabellen vollständig.

Nun möchte ich mir ein Blättermenü erstellen, dass x Benutzer pro Seite auflistet. Dabei ist mir dann aufgefallen...
Für das Menü benötige ich die Menge der Datensätze für die Varianten 1a oder 1b.

Für die Darstellung von 1b mit dem Blättermenü brauch ich aber nur die Datensätze aus tblOrders, welche auf der aktuellen Seite angezeigt werden müssen.

Und jetzt kommt endlich meine Frage ;)
Sollte ich für die Generierung des Blättermenüs beide Tabellen abfragen und alle Daten speichern, so dass ich bereits _alle_ Datensätze vollständig habe?
Oder sollte ich für das Menü 1 Abfrage starten (jeweils 1a o. 1b) und 1 weitere für die betroffenen Datensätze?

Ich find es gerade irritierend, dass ich nur für das Blättermenü alle Daten abfragen muss obwohl ich aus tblOrders nur die Datensätze der gewählten Seite brauch.

I Carsten

  1. مرحبا

    Sollte ich für die Generierung des Blättermenüs beide Tabellen abfragen und alle Daten speichern, so dass ich bereits _alle_ Datensätze vollständig habe?

    Kommt doch auf dein Blättermenü an, wenn du nur einen Link zum vorwärts, und einen Link zum Rückwärtsblättern generierst, brauchst du nicht alle Datensätze, nur weiss dann auch der User nicht, wann und ob das blättern überhaupt ein ende findet.

    Oder sollte ich für das Menü 1 Abfrage starten (jeweils 1a o. 1b) und 1 weitere für die betroffenen Datensätze?

    Du kannst das zählen ja nebenher mit SQL_CALC_FOUND_ROWS erledigen.

    Ich find es gerade irritierend, dass ich nur für das Blättermenü alle Daten abfragen muss obwohl ich aus tblOrders nur die Datensätze der gewählten Seite brauch.

    Das script, dass die Links generiert, muss ja wissen, wieviele Datensätze es gibt, um dementsprechend die Links zu generieren.
    Ich habe mir vor kurzem eine Klasse geschrieben, die so ein Menu generiert, dafür benötigt es aber die anzahl aller Datensätze, da es sonst nicht rechnen kann.

    mfg

    1. Hallo Malcolm Becks,

      Ich habe mir vor kurzem eine Klasse geschrieben, die so ein Menu generiert, dafür benötigt es aber die anzahl aller Datensätze, da es sonst nicht rechnen kann.

      genau darum geht es mir ja.
      Ich muss erst alle Datensätze einlesen, um die Anzahl ermitteln zu können.
      Das geht übrigens auch später mit count(), da die Weiterverarbeitung von PHP übernommen wird.

      Ist das nicht ein bisschen umständlich immer erst alle Datensätze einlesen zu müssen, nur um die gewünschten paar angezeigt zu bekommen?

      Deine Klasse in allen Ehren (bzw. das Beispiel), gefällt mir recht gut, an der Umsetzung allgemein hapert es aber nicht unbedingt. Ich hab wohl eher Verständnisprobleme mit dem Konzept.

      Wenn ich aber tatsächlich immer alle Datensätze einlesen muss, obwohl z.B. nur 10 angezeigt werden sollen, dann ist das halt so ;)

      I Carsten

      1. مرحبا Carsten

        Ich muss erst alle Datensätze einlesen, um die Anzahl ermitteln zu können.
        Das geht übrigens auch später mit count(), da die Weiterverarbeitung von PHP übernommen wird.

        Deswegen schrieb ich ja "SQL_CALC_FOUND_ROWS".
        Ich weiss nicht, ob es am count() liegt, aber fast alle Scripte (die ich so gesehen habe), die mit count() Blättermenus generieren, brauchen ein zusätzliches Select-Statement, um die Datensätze zählen zu können, "SQL_CALC_FOUND_ROWS" liefert dir die Limitierten Daten und die anzahl aller in einem Statement.

        Ist das nicht ein bisschen umständlich immer erst alle Datensätze einlesen zu müssen, nur um die gewünschten paar angezeigt zu bekommen?

        Das ist sehr umständlich und auch nicht nötig.

        Deine Klasse in allen Ehren (bzw. das Beispiel), gefällt mir recht gut, an der Umsetzung allgemein hapert es aber nicht unbedingt. Ich hab wohl eher Verständnisprobleme mit dem Konzept.

        Es dient als einfaches Bsp., wie stellst du dir dein Menu vor, wie soll die bedienung aussehen? Wenn du Bspw. ab der ersten Seite auch auf die letzte Seite der generierten Seiten verlinken willst (wie bei mir), kommst du nicht drum herum, die Anzahl der Daten zu wissen.

        Wenn ich aber tatsächlich immer alle Datensätze einlesen muss, obwohl z.B. nur 10 angezeigt werden sollen, dann ist das halt so ;)

        SQL_CALC_FOUND_ROWS ist das Stichwort.

        mfg

        1. Hallo Malcolm Becks,

          danke für den Hinweis auf SQL_CALC_FOUND_ROWS! Das sieht eigentlich ganz vernünftig aus.
          Ich möchte aber leider nicht die einzelnen Rechnungen auf die Seiten verteilen, sondern die Benutzernamen.

          Z.B. 10 Benutzer pro Seite anzeigen und die dazugehörigen Rechnungen.
          Wenn ich aber die Rechnungen zusammen mit den Benutzernamen abfrage, liefert mir SQL_CALC_FOUND_ROWS natürlich die Menge der Rechnungsnummern und nicht die der _verschiedenen_ Benutzer.

          Zur Verdeutlichung vielleicht hier mein Statement zur Abfrage der Daten

            
          SELECT tblUsers.Id userId,  
                 tblUsers.Benutzername userName,  
                 tblOrders.Id rechnungsId,  
                 tblOrders.RNr rechnungsNummer  
          FROM (SELECT Id, Benutzername  
                FROM tblUsers  
                ORDER BY Id DESC  
                LIMIT 0, 10)  
                tblUsers  
          LEFT JOIN tblOrders  
          ON tblUsers.Id = tblOrders.UserId  
          ORDER BY tblUsers.Id DESC, tblOrders.Id  
          
          

          Irgendwie komm ich da mit SQL_CALC_FOUND_ROWS nicht weiter.

          I Carsten

          1. مرحبا Carsten

              
            
            > SELECT tblUsers.Id userId,  
            >        tblUsers.Benutzername userName,  
            >        tblOrders.Id rechnungsId,  
            >        tblOrders.RNr rechnungsNummer  
            > FROM (SELECT Id, Benutzername  
            >       FROM tblUsers  
            >       ORDER BY Id DESC  
            >       LIMIT 0, 10)  
            >       tblUsers  
            > LEFT JOIN tblOrders  
            > ON tblUsers.Id = tblOrders.UserId  
            > ORDER BY tblUsers.Id DESC, tblOrders.Id  
             
            

            In welchem query hast du SQL_CALC_FOUND_ROWS angewendet?
            Ich hab's nicht getestet, aber ich denke mal, wenn count() in Subquerys funktioniert, müsste es mit SQL_CALC_FOUND_ROWS auch funktionieren.

            mfg

            1. In welchem query hast du SQL_CALC_FOUND_ROWS angewendet?

              In beiden. Im ersten zählt es halt alle Datensätze, im zweiten

              Ich hab's nicht getestet, aber ich denke mal, wenn count() in Subquerys funktioniert, müsste es mit SQL_CALC_FOUND_ROWS auch funktionieren.

              funktioniert es (aber) nicht. Die Fehlermeldung hab ich nicht im Kopf, aber es war an der Stelle nicht erlaubt.

              I Carsten

      2. Hi,

        Ich muss erst alle Datensätze einlesen, um die Anzahl ermitteln zu können.
        Das geht übrigens auch später mit count(), da die Weiterverarbeitung von PHP übernommen wird.

        Ist das nicht ein bisschen umständlich immer erst alle Datensätze einlesen zu müssen, nur um die gewünschten paar angezeigt zu bekommen?

        Ja, eben - wieso willst du es dann machen?

        Erst im PHP-Script die Datensätze zu zählen, ist eine ganz blöde Idee - dazu musst du sie nämlich auch alle erst dorthin „rüberschaufeln“.

        Wenn ich aber tatsächlich immer alle Datensätze einlesen muss, obwohl z.B. nur 10 angezeigt werden sollen, dann ist das halt so ;)

        Nein, so ist es ganz und gar nicht.

        Beschäftige dich mit Aggregatfunktionen der Datenbank, und auch mit dem erwähnten SQL_CALC_FOUND_ROWS.

        MfG ChrisB

        --
        “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
  2. Hallo,

    wie es aussieht, brauch ich wohl mindestens 2 Abfragen.
    Ich denke also über einen anderen Ansatz nach.

    Zunächst SELECT auf die Namen, ggf. mit LIMIT für das Blättermenü, und
    eine weitere Abfrage nach den Rechnungen für die gefundenen Datensätze.

    Nun ist die Frage, wie ich die zweite Abfrage gestalte.
    Kann ich das Ergebnis der ersten Abfrage "zwischenspeichern", so dass ich die zweite Abfrage in der Form SELECT [..] WHERE UserId IN (-erstes Result-)[..] schreiben kann?

    I Carsten