Christian Naggert: Nächsten Datensatz auf Inhalt eines Feldes überprüfen

Hallo,

ich habe folgendes Problem:

Ich rufe eine MySQL-DB mit einer ID auf. Der entprechende Datensatz soll dann angezeigt werden (klappt auch).

Jetzt möchte ich überprüfen, ob in dem nächsten oder darauffolgendem Datensatz das Feld 'anzeigen' eine 1 oder eine 0 enthält.
Wenn es eine 1 enthält, möchte ich die dazugehörige ID in einer Variablen speichern.
Wenn es eine 0 enthält, möchte ich den nächsten Datensatz überprüfen und wenn ja, gegebenenfalls die zugehörige ID speichern.

Das soll solange geschehen, bis entweder das Ende der Tabelle erreicht ist oder ein entsprechender Datensatz gefunden worden ist.

Ich benutze zur Zeit folgenden Code:

<? include("class.mysql.inc");
 $connect=new mySQLDB;
 $connect->connect();

// Aufruf des anzuzeigenden Datensatzes mit der entsprechenden ID,
// die ich in der URL mit übergebe

$tmp="SELECT * FROM angebote WHERE id = '$id'";
 $connect->do_query($tmp);
 $connect->getrow();

$objektnr=$connect->field("objektnr");
 $id=$connect->field("id");
 $zeile1=$connect->field("zeile_eins");

// ab hier möchte ich den nächsten Datensatz überprüfen

$erg = "SELECT * FROM angebote";
$num = mysql_num_rows($erg);
for ($i=$id;$i<$num; i++)
{
$next[$i] = mysql_result($erg, $i, "anzeigen");
if ($next[$i] == 1) {echo $next[$i];break;}
};
?>

mit
angebote = Tabellenname
$erg = neue Abfragequery
$num = Anzahl der Zeilen
$next = Vaiable, in der die gefundene ID gespeichert werden soll
anzeigen = Spaltenname in der das Feld überprüft werden soll

Es klappt aber nicht und ich habe nicht die leiseste Ahnung warum ?!?

Über Hilfe, wäre ich sehr dankbar!

Gruß,
Christian

  1. Huhu Christian

    $tmp="SELECT * FROM angebote WHERE id = '$id'";

    $tmp.="AND anzeigen=1";

    wäre evtl. eine Lösung

    Viele Grüße
    lulu

    1. Huhu Christian

      $tmp="SELECT * FROM angebote WHERE id = '$id'";

      $tmp.="AND anzeigen=1";

      wäre evtl. eine Lösung

      Viele Grüße
      lulu

      Wenn ich ganz ehrlich bin, weiss ich damit nicht recht etwas anzufangen ;-(

      Ist mein Ansatz denn komplett falsch?
      Kann man da nicht irgendetwas machen?

      Gruß und trotzdem schon mal danke,
      Christian

      1. Huhu Christian

        Ist mein Ansatz denn komplett falsch?
        Kann man da nicht irgendetwas machen?

        ich behaupte einfach mal das jeder der vorher mit Flatfiles also einfachen Ascii-Dateien als Datenspeicher gearbeitet hat am Anfang Probleme mit Datenbanken hat. Bei Datenbanken können Begriffe wie erster, letzter oder nächster Eintrag nicht so verwandt werden wie bei sequentiellen Textdateien, da es hierbei immer auf die jeweilige Auswahl (Teilmenge der Datensätze) ankommt.
        Das Grund-Prozedere ist aber eigentlich gar nicht so schwer.

        Aus der Menge aller vorhandenen Datensätze wählt man per SQL-Statement eine Teilmenge aus. Also mit einer WHERE bedingung. Mehrere Bedingungen können logisch miteinander verknüpft werden.
        Diese Teilmenge kann man sich zusätzlich nach einem oder auch mehreren Spalten ordnen lassen.
        Das Ergebnis kann natürlich auch nur ein einzelner Datensatz sein, oder eine leere Menge wenn es zu dem SQL-Statement keinen passenden Eintrag gibt.

        Das wichtigste und vielleicht schwierigste an der Materie ist IMHO die Konzeption der DB, also wie man welche Informationen auf mehrere DB-Tables verteilt.

        Vielleicht erläuterst Du nochmal was das Feld "anzeigen" bei Dir bedeutet, ich habe es so verstanden, dass es eine Art Flag ist, welches festlegt ob ein Datensatz aktiv ist, also zur Menge der Datensätze gehört welche zur Auswahl stehen sollen.
        Daher mein Vorschlag per " AND anzeigen='1' " nur die Datensätze zu berücksichtigen die dieses Flag gesetzt haben.

        Viele Grüße

        lulu

        1. Hallo lulu,

          ersteinmal vielen Dank, dass du dir so viel Zeit nimmst!

          Ich habe eine Art Dia-Show. Diese funktioniert so, dass alle 8 Sekunden
          eine neue Seite geladen wird.

          In HEAD-Bereich jeder Seite befindet sich nun der Refresh-Befehl, der eine
          neue Seite lädt. Hier habe ich immer ...php?id=1 (z.B.) angegeben.
          Des weiteren gibt es einen vor- und zurück- Button, der einem die manuelle
          Navigation ermöglicht, falls man die Refresh-Funktion durch den von mir
          eingesetzten Pause-Button ausser Kraft gesetzt hat.

          Über den Admin-Bereich kann man nun auswählen, ob ein Datensatz angezeigt
          werden soll oder nicht. Im Falle eines 'JA' speichere ich im Feld 'anzeigen'
          eine '1', ansonsten eine '0'.

          In der Dia-Show sollen dementsprechend nur die Datensätze angezeigt werden,
          die im Feld 'anzeigen' eine '1' stehen haben. Wenn eine '0' in diesem Feld
          steht, soll dieser Datensatz übersprungen werden. Das muss ich nun irgendwie
          dem Refresh-Befehl und den vor- und zurück-Buttons klarmachen. Aus diesem Grund
          hatte ich versucht den nächsten Datensatz auszulesen, der im Feld 'anzeigen'
          eine '1' hat und wollte dann die zugehörige ID in einer Variable ($next) abspei-
          chern. Das hat ja irgendwie nicht geklappt, warum auch immer.

          Jetzt habe ich dich wahrscheinlich mit Infos erschlagen, sorry!

          Vielleicht weisst du ja irgendwas, was man da machen kann!

          Viele Grüße und vielen Dank,
          Christian

        2. Hallo lulu,

          nachdem mir das nun etwas klarer geworden ist, verstehe ich, was du meinst :-)

          Was ich allerdings noch nicht weiss ist, wie ich dann zum nächsten Datensatzt springe?
          Sonst habe ich ja einfach nur mit ...php?id= die ID angegeben.

          Ich verknüpfe ja am Anfang die Seite mit der DB durch
          $tmp="SELECT * FROM angebote WHERE id = '$id'".
          Dann würde ich ja nun schreiben
          $tmp="SELECT * FROM angebote WHERE id = '$id' AND anzeigen = 1"

          Gibt es da einen Befehl, der zum nächsten Datensatz in der erstellten Query $tmp springt?
          Den könnte ich dann doch bestimmt irgendwie als Link angeben, oder?

          Gruß,
          Christian

          1. Hi Christian,

            Gibt es da einen Befehl, der zum nächsten Datensatz in der
            erstellten Query $tmp springt?
            Den könnte ich dann doch bestimmt irgendwie als Link
            angeben, oder?

            Deine Denkweise ist nicht kompatibel zu derjenigen Deiner Problem-Architektur. ;-)

            Aus Deiner obigen Beschreibung schließe ich, daß Du via HTTP im Wesentlichen zwischen den verschiedenen Treffern einer Abfrage blättern willst - richtig?

            Du gehst dabei implizit davon aus, daß irgendwer sich nach dem Klicken auf besagten Link noch an das Ergebnis einer vorherigen Datenbankabfrage erinnern würde.

            Genau das ist aber das Problem. Wer sollte das sein?
            Dein vorheriger Prozeß (egal ob CGI oder PHP oder ...) hat eine Abfrage gegen die Datenbank geworfen und ein Ergebnis zurück bekommen, dieses als HTML-Seite an einen Browser gesendet und sich danach beendet.
            Niemand weiß mehr, was der genau getan hat - insbesondere die Datenbank nicht, welche in der Zwischenzeit einen Haufen anderer Anforderungen bekommen hat und eine beliebige weitere Anforderung nicht mehr als der vorherigen zugehörig erkennen kann (keine etablierte Session).

            Alles, was der nächste Datenbankzugriff tun kann, ist, wieder eine neue Anforderung (im Wesentlichen dieselbe wie zuvor) zu stellen - wobei er (mit Hilfe des Query-Strings des URLs in dem von Dir erwähnten Link) immerhin die Chance hat, eine gegenüber der vorherigen Anforderung _abweichende_ Anfrage zu verursachen.
            Du kannst also dadurch blättern, daß Du jedesmal _alle_ in Frage kommenden Datensätze aus der Datenbank abfragst, von diesen aber nur den <n>-ten Datensatz wirklich abgreifst (LIMIT-Klausel).
            Und die Position des gewünschten Datensatzes kannst Du (als jeweils um 1 erhöhten Zahlenwert) jeweils in den Query-String der URL desjenigen Links eintragen, den Du bei der Anzeige einer vorherigen Seite mit einblendest. Vorwärts- und Rückwärtsblättern unterscheiden sich dabei genau um ein Vorzeichen. (Sonderbehandlung am Anfang - leicht - und Ende der Liste - etwas schwerer - nicht vergessen!)

            Blättern über die ID geht deshalb nicht os einfach, weil Du sämtliche (!) Seiten ja so generieren müßtest, daß jeweils die ID der nachfolgenden Seite in dem Link eingetragen ist - und wer soll sich diese IDs in der Zwischenzeit wo merken?
            Du kannst alternativ sowohl die Daten der angezeigten Seite als auch diejenigen der Nachfolgeseite bei jeder Query anfordern, dann kannst Du immerhin den Nachfolge-Link generieren - das bedeutet aber nur, daß Du diese Daten zweimal abholen mußt (sowohl bei der Anzeige des Vorgängers als auch bei der Anzeige der Seite selbst), während das bei meiner skizzierten Lösung nur einmal erforderlich ist.
            Alternative: Du fügst in jeden Datensatz die ID des Vorgängers bzw. Nachfolgers als zusätzliche Spalte ein, d. h. Du gibst das Konzept einer Menge auf und konstruierst eine verkettete Liste - mit allen Nachteilen, die das bezüglich Einfügen, Löschen und sortierter Gesamt-Ausgabe im Vergleich zu einer Menge hat.

            Viele Grüße
                  Michael

            1. Hallo Michael,

              Aus Deiner obigen Beschreibung schließe ich, daß Du via HTTP im Wesentlichen zwischen den verschiedenen Treffern einer Abfrage blättern willst - richtig?

              Genau das habe ich vor.

              Du gehst dabei implizit davon aus, daß irgendwer sich nach dem Klicken auf besagten Link noch an das Ergebnis einer vorherigen Datenbankabfrage erinnern würde.

              Sehe ich ein, war wohl nix :-(

              Alles, was der nächste Datenbankzugriff tun kann, ist, wieder eine neue Anforderung (im Wesentlichen dieselbe wie zuvor) zu stellen - wobei er (mit Hilfe des Query-Strings des URLs in dem von Dir erwähnten Link) immerhin die Chance hat, eine gegenüber der vorherigen Anforderung _abweichende_ Anfrage zu verursachen.

              Habe ich versucht! Ich möchte ja den nächsten Datensatz haben, der eine höhere ID hat und im Feld 'anzeigen' eine 1 stehen hat. Ich hatte in einem anderen Forum etwas von '$currentid' gelesen. Ich gedacht, dass könnte ich benutzen, um eine Abfrage zu erstellen, die mir alle Datensätze auswirft, die eine höre ID haben als meine aktuelle:

              $new="SELECT * FROM angebote WHERE id > '$currentid' AND anzeigen = 1 ORDER BY id LIMIT 1";

              Klappt aber nicht, dann habe ich:

              $new="SELECT * FROM angebote WHERE id > '$id' AND anzeigen = 1 ORDER BY id LIMIT 1";

              ausprobiert geht aber auch nicht :-( Er landet immer beim ersten Datensatz in der Tabelle).

              Selbst wenn das klappen würde, klappt das mit der id auch irgendwie nicht. Ich habe dann eben mit dem ersten Datensatz der Tabelle herumexperimentiert. Ich konnte mir die Daten der ersten Abfrage und auch alle Felder der zweiten Abfrage anzeigen lassen, aber nicht die id (eingelesen in $id_new):

              $new="SELECT * FROM angebote WHERE id > '$id' AND anzeigen = 1 ORDER BY id LIMIT 1";
               $connect->do_query($new);
               $connect->getrow();

              $objektnr=$connect->field("objektnr");
               $id_new=$connect->field("id");
               $zeile_new=$connect->field("zeile_eins");

              Mit dem Befehl <? echo $id_new ?> erhielt ich keine Anzeige?!?

              Du kannst also dadurch blättern, daß Du jedesmal _alle_ in Frage kommenden Datensätze aus der Datenbank abfragst, von diesen aber nur den <n>-ten Datensatz wirklich abgreifst (LIMIT-Klausel).

              Blättern über die ID geht deshalb nicht so einfach, weil Du sämtliche (!) Seiten ja so generieren müßtest, daß jeweils die ID der nachfolgenden Seite in dem Link eingetragen ist - und wer soll sich diese IDs in der Zwischenzeit wo merken?

              Gut, wenn ich weiss, wie man den nächsten abfragt (mit $currentid oder wie auch immer), muss es doch möglich sein, diese ID auszulesen und in einen Link zu packen! Ich verstehe das nicht, das muss doch irgendwie machbar sein. Warum kann man nicht einfach eine Liste der nachfolgenden Datensätze (geordnet nach id) ausgeben und sagen 'nextrow' oder einfach vom ersten Dastensatz die ID auslesen und in den Link packen?

              Ich glaube, dass ist alles eine Nummer zu hoch für mich, dummerweise muss ich es irgendwie fertig bekommen, sonst bekomme ich ne Menge Stress.

              Tut mir leid, dass ich deine Zeit so lange beanspruche, aber vielleicht kannst du mir nochmal helfen ???

              Viele Grüße,
              Christian

              1. Hi Christian,

                $new="SELECT * FROM angebote WHERE id > '$currentid'
                AND anzeigen = 1 ORDER BY id LIMIT 1";

                Nicht ganz das, was Du willst, aber schon nicht schlecht.

                ausprobiert geht aber auch nicht :-( Er landet immer beim ersten
                Datensatz in der Tabelle).

                Schau Dir die Limit-Klausel noch mal genau an. Die kann mehr, als Du bisher nutzt - und das wird Dein Problem lösen. (Dafür wird dann Deine WHERE-Klausel kürzer.)

                Tut mir leid, dass ich deine Zeit so lange beanspruche, aber
                vielleicht kannst du mir nochmal helfen ???

                Der entscheidende Hinweis war schon in der vorherigen Mail, nämlich:

                Du kannst also dadurch blättern, daß Du jedesmal _alle_ in Frage
                kommenden Datensätze aus der Datenbank abfragst, von diesen aber
                nur den <n>-ten Datensatz wirklich abgreifst (LIMIT-Klausel).

                Die kann nämlich mehr als nur einen Parameter haben ...

                Viele Grüße
                      Michael

                1. Hi Christian,

                  $new="SELECT * FROM angebote WHERE id > '$currentid'
                  AND anzeigen = 1 ORDER BY id LIMIT 1";

                  Nicht ganz das, was Du willst, aber schon nicht schlecht.

                  Verstehe ich nicht ganz, warum es nicht das sein soll, was ich möchte, denn ich möchte doch eine Liste der Datensätze, die a) eine größere ID als die aktuelle haben (id > '$currentid') und b) im Feld anzeigen eine 1 stehen haben. Aus der Liste möchte ich dann den ersten Datensatz haben (LIMIT 1). Ich lasse mir ja auf der Seite immer ein Feld ($zeile_eins) aus dem "gefundenen" Datensatz anzeigen und das ist immer der zweite Datensatz meiner Gesamttabelle, nicht aber der von mir ausgeführten Abfrage. Klappt vielleicht das mit $currentid nicht?

                  Mein gesamter Code sieht mittlerweile so aus:

                  <? include("class.mysql.inc");
                   $connect=new mySQLDB;
                   $connect->connect();

                  $tmp="SELECT * FROM angebote WHERE id = '$id'";
                   $connect->do_query($tmp);
                   $connect->getrow();

                  $objektnr=$connect->field("objektnr");
                   $id=$connect->field("id");
                   $zeile1=$connect->field("zeile_eins");

                  $new="SELECT * FROM angebote WHERE id > '$currentID' AND anzeigen = 1 LIMIT 1";
                   $connect->do_query($new);
                   $connect->getrow();

                  $objektnr=$connect->field("objektnr");
                   $id_new=$connect->field("id");
                   $zeile_new=$connect->field("zeile_eins");
                  ?>

                  Schau Dir die Limit-Klausel noch mal genau an. Die kann mehr, als Du bisher nutzt - und das wird Dein Problem lösen. (Dafür wird dann Deine WHERE-Klausel kürzer.)

                  Das mit der LIMIT Klausel habe ich mir angeschaut, sehe aber nicht ganz den Vorteil, einer weiteren Angabe, da ich doch nur wirklich eine Zeile (Datensatz) benötige, nämlich den ersten mit einer größeren ID als der aktuellen. Ich weiss dementsprechend nicht, wie ich weitere Parameter geschickt einsetzen sollte. Das müsste doch mit LIMIT 1 machbar sein, da, wenn ich das richtig verstanden habe, dann die erste Zeile der Abfrageliste angezeigt wird.

                  Der entscheidende Hinweis war schon in der vorherigen Mail, nämlich:

                  Du kannst also dadurch blättern, daß Du jedesmal _alle_ in Frage
                  kommenden Datensätze aus der Datenbank abfragst, von diesen aber
                  nur den <n>-ten Datensatz wirklich abgreifst (LIMIT-Klausel).

                  Ich habe auch mal LIMIT n ausprobiert, dann zeigt er mir aber wieder nix oder habe ich da was nicht kapiert?

                  Ich weiss, ich bin ein schwerer Fall, aber ich lerne eifrig und hoffe, dass ich es noch schaffe :-)

                  Viele Grüße
                  Christian

                  1. Hallo Michael (soory, hatte ich in der Nachricht vorher vergessen),

                    mir ist da noch ein Fehler unterlaufen:

                    Mein gesamter Code sieht mittlerweile so aus:

                    ...

                    $new="SELECT * FROM angebote WHERE id > '$id' AND anzeigen = 1 LIMIT 1";

                    Ist es eigentlich entscheidend, ob man die Abfrage id > '$id$' in diese ''-Zeichen setzt. Wenn ich sie weglasse, zeigt er mit gar nichts aus dem neu gefundenen (Query 2) Datensatz an?

                    Gruß und vielen Dank,
                    Christian

                    1. Hallo Michael,

                      peinlich, peinlich:

                      nicht '$id$', sondern '$id'

                      Tut mir leid. Gruß,
                      Christian

                2. Hallo Michael,

                  es klappt nun alles.

                  Nach langem hin und her und einiger Tüftelei habe ich es nun geschafft!

                  Deine Tipps habe ich am Anfang zwar als etwas schwer verstanden, aber das lag natürlich auch daran, dass ich noch so gut wie gar keine Ahnung hatte. Im Nachhinein war es aber echt gut mir nicht gleich die Lösung zu präsentieren, denn so ahbe ich jetzt wirklich was gelernt!

                  Vielen, vielen Dank nochmals und viele Grüße,
                  Christian

                  1. Hi Christian,

                    Deine Tipps habe ich am Anfang zwar als etwas schwer verstanden,
                    aber das lag natürlich auch daran, dass ich noch so gut wie gar
                    keine Ahnung hatte.
                    Im Nachhinein war es aber echt gut mir nicht gleich die Lösung zu
                    präsentieren, denn so ahbe ich jetzt wirklich was gelernt!

                    aaaah - am liebsten möchte ich mir dieses Posting einrahmen und an die Wand hängen ... hier hat jemand den Self-Gedanken voll verinnerlicht!

                    Zufriedene Grüße
                               Michael

        3. Hi lulu,

          Bei Datenbanken können Begriffe wie erster, letzter oder
          nächster Eintrag nicht so verwandt werden wie bei
          sequentiellen Textdateien, da es hierbei immer auf die
          jeweilige Auswahl (Teilmenge der Datensätze) ankommt.

          meiner Meinung nach besteht ein wesentlicher Teil der erforderlichen Umstellung beim Denken in SQL darin, zu akzeptieren, daß SQL in Mengen denkt und nicht in Listen.

          Mengen sind in den meisten Fällen implizit duplikatcfrei; dafür sind sie aber auch zunächst einmal ungeordnet.

          Eine Abfrage auf eine Menge, welche in einer konventionellen Programmiersprache weiter verarbeitet werden soll, erfordert also eine Umsetzung einer Menge in eine Liste, was (explizit durch ORDER BY oder implizit) eine Ordnung auf die Elemente der Liste anwendet, welche gemäß dieser Ordnung nacheinander (FETCH etc.) in eine sequentielle Datenstruktur der konventionellen Programmiersprache übertragen wird.

          Das wichtigste und vielleicht schwierigste an der Materie
          ist IMHO die Konzeption der DB, also wie man welche
          Informationen auf mehrere DB-Tables verteilt.

          Dem stimme ich uneingeschränkt zu.

          Viele Grüße
                Michael

  2. Mach doch ein

    SELECT * FROM tabelle
    WHERE id > $id
    AND ausgeben = 0
    ORDER BY id ASC

    Dann loopst Du über das Resultat und brichst ab, wenn die $id vom Schritt N+1 größer als die $id vom Schritt N, plus 1, ist (d.h. wenn nicht zwei aufeinanderfolgende Nullen in der Tabelle waren).

    1. Mach doch ein

      SELECT * FROM tabelle
      WHERE id > $id
      AND ausgeben = 0
      ORDER BY id ASC

      Dann loopst Du über das Resultat und brichst ab, wenn die $id vom Schritt N+1 größer als die $id vom Schritt N, plus 1, ist (d.h. wenn nicht zwei aufeinanderfolgende Nullen in der Tabelle waren).

      Hi,

      ich glaube ich geb's auf. Ich weiss jetzt leider überhaupt nicht mehr was ich machen soll, sorry. Ich fange doch gerade erst an mit PHP und habe meine alten Kentnisse aus Basic mit den Selfhtml-Forumsbeiträgen kombiniert. Aber das ist nun doch ne Nummer zu hoch für mich! Ich dachte ich wäre auf einem guten Weg gewesen, war wohl nix. Muss mich wohl oder übel durch die Literatur quälen, bevor ich euch hier weiter bemühe!

      Trotzdem vielen Dank für eure Antworten und Bemühungen!

      Liebe Grüße,
      Christian