[PHP+MYSQL] Nested while loop

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • silentkiller
  • Registratie: Februari 2003
  • Laatst online: 19-09 08:06
Hallo allemaal,
Op school heb ik leren werken met dreamweaver. Hiermee kun je makkelijk recordsets aanmaken en beheren. Echter als het wat verder gaat dan dat moet je in de code gaan kijken en daar loop ik dus vast op iets.
Ik haal eerst twee dingen op in twee verschillende tabellen:

PHP:
1
2
3
4
5
6
7
8
9
10
11
mysql_select_db($database_database, $database);
$query_rsNaam = "SELECT naam FROM tbl_Lid";
$rsNaam = mysql_query($query_rsNaam, $database) or die(mysql_error());
$row_rsNaam = mysql_fetch_assoc($rsNaam);
$totalRows_rsNaam = mysql_num_rows($rsNaam);

mysql_select_db($database_database, $database);
$query_rsOverschrijvingen = "SELECT overschrijvingnr FROM tbl_Overschrijvingen";
$rsOverschrijvingen = mysql_query($query_rsOverschrijvingen, $database) or die(mysql_error());
$row_rsOverschrijvingen = mysql_fetch_assoc($rsOverschrijvingen);
$totalRows_rsOverschrijvingen = mysql_num_rows($rsOverschrijvingen);


En daarna maak ik een nested do while:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<table border="1">
  <tr>
    <td>naam</td>
    <td>overschrijvingsnummers</td>
  </tr>
  <?php do { ?>
    <tr>
      <td><?php echo $row_rsNaam['naam']; ?></td>
      <td>
      <?php 
      
      do { 
      echo $row_rsOverschrijvingen['overschrijvingnr']  . "<br/>"; 
      } while ($row_rsOverschrijvingen = mysql_fetch_assoc($rsOverschrijvingen));
      ?>
      </td>
    </tr>
    <?php } while ($row_rsNaam = mysql_fetch_assoc($rsNaam)); ?>
</table>

Het probleem is nu dat hij de eerst keer de inner while loop goed doorloopt maar de volgende keren niet meer omdat de inner loop al eens doorlopen is. Ik wilde het zo oplossen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
mysql_select_db($database_database, $database);
$query_rsNaam = "SELECT naam FROM tbl_Lid";
$rsNaam = mysql_query($query_rsNaam, $database) or die(mysql_error());
$row_rsNaam = mysql_fetch_assoc($rsNaam);
$totalRows_rsNaam = mysql_num_rows($rsNaam);

mysql_select_db($database_database, $database);
$query_rsOverschrijvingen = "SELECT overschrijvingnr FROM tbl_Overschrijvingen";
$rsOverschrijvingen = mysql_query($query_rsOverschrijvingen, $database) or die(mysql_error());
=====>$rsOverschrijvingenBegin = $rsOverschrijvingen;
$row_rsOverschrijvingen = mysql_fetch_assoc($rsOverschrijvingen);
=====>$row_rsOverschrijvingenBegin = $row_rsOverschrijvingen;
$totalRows_rsOverschrijvingen = mysql_num_rows($rsOverschrijvingen);
?>
<table border="1">
  <tr>
    <td>naam</td>
    <td>overschrijvingsnummers</td>
  </tr>
  <?php do { ?>
    <tr>
      <td><?php echo $row_rsNaam['naam']; ?></td>
      <td>
      <?php 
        =====>$rsOverschrijvingen = $rsOverschrijvingenBegin;
        =====>$row_rsOverschrijvingen = $row_rsOverschrijvingenBegin;
      do { 
      echo $row_rsOverschrijvingen['overschrijvingnr']  . "<br/>"; 
      } while ($row_rsOverschrijvingen = mysql_fetch_assoc($rsOverschrijvingen));
      ?>
      </td>
    </tr>
    <?php } while ($row_rsNaam = mysql_fetch_assoc($rsNaam)); ?>
</table>

(4 extra lijnen aangegeven door '=====>')
Dit is al beter maar nu laat hij nog maar enkel de eerst row zien van $rsOverschrijvingen en niet alle rijen (hij doet de do maar 1 keer en voldoet direct aan de while). Echter zie ik niet in waarom. Hopelijk iemand van jullie wel :)

Alvast bedankt !

Acties:
  • 0 Henk 'm!

Verwijderd

Ik denk dat het op deze manier een stuk makkelijker gaat dan een do/while http://nl2.php.net/mysql_fetch_assoc

Kijk voorral naar dit gedeelte:
code:
1
2
3
4
5
while ($row = mysql_fetch_assoc($result)) {
    echo $row["userid"];
    echo $row["fullname"];
    echo $row["userstatus"];
}



voor de rest: je verhaal is heel onduidelijk, wat staat er in de tabellen? hebben deze een relatie met elkaar? zo ja dan is dit misschien in de query al op te lossen.

Wat wil je precies met je code doen?
Iets meer uitleg graag.

[ Voor 28% gewijzigd door Verwijderd op 22-01-2010 23:00 ]


Acties:
  • 0 Henk 'm!

  • Sp33dFr34k
  • Registratie: Juni 2006
  • Niet online

Sp33dFr34k

Retro-Geek

Vanwaar de do while ipv gewoon while?

Hij showed maar 1 record omdat de conditie gechecked wordt na de do. Daarom wil je hier een gewone while loop gebruiken ipv een while do. Punt is dus dat je conditie niet goed is...

Edit: what ^^ says...

[ Voor 84% gewijzigd door Sp33dFr34k op 22-01-2010 23:00 ]

i7 9700k + Be-Quiet Dark Rock 4 Pro | Gigabyte Z390 Aorus Ultra | Gigabyte RTX5070Ti | Samsung 970 Pro 512GB + 860 EVO 1TB + 860 QVO 4TB | 2x8GB DDR4 3000Mhz | Seasonic Platinum 660W | Fractal Design R6 | Samsung Oddyssey G7 Neo | Edifier M60


Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 01:20

MueR

Admin Tweakers Discord

is niet lief

silentkiller schreef op vrijdag 22 januari 2010 @ 22:51:
PHP:
1
} while ($row_rsNaam = mysql_fetch_assoc($rsNaam));
There's your problem.

En @ bovenstaande posters:
Het maakt an sich niet uit of je nu do...while of een normale while loop gebruikt. Zolang je vantevoren maar controleert of je daadwerkelijk resultaten hebt, krijg je bij beiden een correct resultaat (mits je bij do..while wel even de eerste row ophaalt). TS doet die controle overigens niet.

[ Voor 45% gewijzigd door MueR op 22-01-2010 23:08 ]

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • Sp33dFr34k
  • Registratie: Juni 2006
  • Niet online

Sp33dFr34k

Retro-Geek

Klopt, maar zoals ik al zei is de conditie niet goed.

De regels:

$row_rsNaam = mysql_fetch_assoc($rsNaam);
$row_rsOverschrijvingen = mysql_fetch_assoc($rsOverschrijvingen);

moeten weg, hij doet nu een fetch op een fetch.

i7 9700k + Be-Quiet Dark Rock 4 Pro | Gigabyte Z390 Aorus Ultra | Gigabyte RTX5070Ti | Samsung 970 Pro 512GB + 860 EVO 1TB + 860 QVO 4TB | 2x8GB DDR4 3000Mhz | Seasonic Platinum 660W | Fractal Design R6 | Samsung Oddyssey G7 Neo | Edifier M60


Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 01:20

MueR

Admin Tweakers Discord

is niet lief

Sp33dFr34k schreef op vrijdag 22 januari 2010 @ 23:11:
Klopt, maar zoals ik al zei is de conditie niet goed.

De regels:

$row_rsNaam = mysql_fetch_assoc($rsNaam);
$row_rsOverschrijvingen = mysql_fetch_assoc($rsOverschrijvingen);

moeten weg, hij doet nu een fetch op een fetch.
Nee? Hij doet een fetch op resultset $rsNaam en een fetch op resultset $rsOverschrijvingen.

De conditie is prima. Er zit alleen een klein ander probleem in de regel die ik highlightte. Oh ja, en voor degene die het probleem in die regel ziet, doe me een lol en geef de TS wat tijd om te proberen het zelf te zien. Dit is iets wat iedere programmeur ergens een keer doet en het kost meestal heel veel tijd om ze te vinden.

[ Voor 27% gewijzigd door MueR op 22-01-2010 23:25 ]

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • silentkiller
  • Registratie: Februari 2003
  • Laatst online: 19-09 08:06
Heren,
Ik zie ook het probleem niet in van een do.. while ipv een while. Dreamweaver genereert een do..while voor een repeating region, dus gebruik ik die (hij werkt overigens perfect). Morgen zal ik even toelichten wat de bedoeling is en hoe de tabellen met elkaar verbonden zijn maar dan ga ik enige screens moeten nemen.
Bedankt alvast voor jullie snelle hulp, ik lees het morgen aandachtig door als ik mijn ogen beter open blijven want ik zie nu niet direct het probleem in.

Nogmaals bedankt :)

Edit: ik ga het inderdaad proberen zelf uit te zoeken. Als je het dan vindt, dan maak je die fout meestal niet meer ;)

[ Voor 10% gewijzigd door silentkiller op 22-01-2010 23:29 ]


Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 01:20

MueR

Admin Tweakers Discord

is niet lief

silentkiller, doe jezelf een lol: laat Dreamweaver nooit, never, code voor je genereren. Zorg dat je zelf snapt hoe het werkt. Zoals ik aanhaalde mis je een vrij belangrijk stuk voor je loop: controle of je uberhaupt wel resultaten krijgt. Dit soort dingen worden vrijwel nooit door dit soort "sleur en pleur" editors meegenomen in de code (om nog maar te zwijgen van de gruwelijke code). Debuggen in code die je niet goed kent is echt een ramp, zeker als je code hebt gegenereerd.
silentkiller schreef op vrijdag 22 januari 2010 @ 23:28:
Edit: ik ga het inderdaad proberen zelf uit te zoeken. Als je het dan vindt, dan maak je die fout meestal niet meer ;)
Echt wel. Ik heb acht jaar ervaring als php programmeur (4 professioneel) en precies deze fout heeft me een paar weken terug nog een uur gekost voor ik hem vond.

[ Voor 29% gewijzigd door MueR op 22-01-2010 23:33 ]

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • silentkiller
  • Registratie: Februari 2003
  • Laatst online: 19-09 08:06
Eerst ben ik opzoek gegaan naar de fout die MueR aangaf maar ik kon het niet direct vinden. Toen heb ik het zo opgelost:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<table border="1"> 
  <tr> 
    <td>naam</td> 
    <td>overschrijvingsnummers</td> 
  </tr> 
  <?php do { ?> 
    <tr> 
      <td><?php echo $row_rsNaam['naam']; ?></td> 
      <td> 
      <?php  
       mysql_data_seek($rsBetalingen,0);

      while ($row_rsOverschrijvingen = mysql_fetch_assoc($rsOverschrijvingen))  {  
      echo $row_rsOverschrijvingen['overschrijvingnr']  . "<br/>";  
      } 
      ?> 
      </td> 
    </tr> 
    <?php } while ($row_rsNaam = mysql_fetch_assoc($rsNaam)); ?> 
</table>

Ik heb er dus een while van gemaakt en net voor de while zet ik de row terug op nul met mysql_data_seek($rsBetalingen,0).
Dit werkt. Waarom ik deze code gebruik (wat ik poste was een simpelere vorm):
Er zijn 4 tabellen:
tbl_Lid (lidnummer,groep,naam)
tbl_kampDeelnemer (overschrijvingNR,lidnummer, kampID)
tbl_Kamp(kampID, kampOmschrijving, prijsGroep1, prijsGroep2, prijsGroep3, prijsGroep4)
tbl_Overschrijvingen (overschrijvingNR, bedrag)

Een kampDeelnemer is een lid dat deelneemt aan een bepaald kamp. Een kamp deelnemer heeft een overschrijvings mededeling voor de bank (overschrijvingNR). In tbl_Overschrijvingen zit een export van de bank (welke overschrijvingen er zijn gebeurd en welk bedrag).

Ik haal alle leden die deelnemen aan een kamp uit de database (welk kamp wordt geselecteerd door een url parameter):
code:
1
SELECT * FROM tbl_Kamp, tbl_Kampdeelnemer, tbl_Lid WHERE tbl_Kamp.kampID = " . $_GET['kampID'] . " AND tbl_Kampdeelnemer.lidnummer = tbl_Lid.lidnummer AND tbl_Kampdeelnemer.kampID = "  . $_GET['kampID'] . " ORDER BY tbl_Lid.naam ASC";

Ik laat elk lid zien in een tabel (eerst while loop) en wil controleren of ze betaald hebben (in een tweede while loop kijk ik of de tbl_kampDeelnemer.overschrijvingnNR gelijk is aan één van de overschrijvingsnummers in tbl_Overschrijvingen. Als dit zo is dan hebben ze betaald. Aan de hand van het bedrag en de groep kan ik dan nog eens afleiden of dat de betaling volledig klopt.

Ik weet niet hoe ik dit kan oplossen met SQL. Mijn oplossing werkt wel maar het enige jammer is dat ik niet kan filteren op betaald, niet betaald of fout bedrag.

Als het niet duidelijk is dan zeg je het maar :)

Acties:
  • 0 Henk 'm!

  • Raynman
  • Registratie: Augustus 2004
  • Laatst online: 01:04
Ik begrijp ook niet wat MueR bedoelde (wat je beschreef van het vertoonde gedrag lijkt me normaal). Maar wat je doet, ziet er wel een beetje vreemd uit. Wat sowieso mij niet duidelijk is: bij wijze van test, en dus bij wat je hier aan code presenteert, druk je die overschrijvingsnummers gewoon af, maar eigenlijk wil je met een if o.i.d. kijken of die nummers gelijk zijn? Kun je niet een join doen op overschrijvingNR? Zo niet (maar dat lijkt me onwaarschijnlijk), dan kun je misschien ook nog ervoor kiezen om slechts een keer die resultset te doorlopen en een array te maken met overschrijvingNR als key en bedrag als waarde en vervolgens daarin te zoeken.

Verder had je er geen while van hoeven maken, alleen die mysql_data_seek($rsBetalingen,0) doet het hem. Maar met een do-while moet je op twee plaatsen mysql_fetch_assoc gebruiken (een keer voor de lus en een keer in de conditie), vandaar de vraag waarom je dat doet, maar dat komt dus door Dreamweaver (?).

Acties:
  • 0 Henk 'm!

  • silentkiller
  • Registratie: Februari 2003
  • Laatst online: 19-09 08:06
Raynman schreef op zaterdag 23 januari 2010 @ 11:24:
Ik begrijp ook niet wat MueR bedoelde (wat je beschreef van het vertoonde gedrag lijkt me normaal). Maar wat je doet, ziet er wel een beetje vreemd uit. Wat sowieso mij niet duidelijk is: bij wijze van test, en dus bij wat je hier aan code presenteert, druk je die overschrijvingsnummers gewoon af, maar eigenlijk wil je met een if o.i.d. kijken of die nummers gelijk zijn? Kun je niet een join doen op overschrijvingNR? Zo niet (maar dat lijkt me onwaarschijnlijk), dan kun je misschien ook nog ervoor kiezen om slechts een keer die resultset te doorlopen en een array te maken met overschrijvingNR als key en bedrag als waarde en vervolgens daarin te zoeken.

Verder had je er geen while van hoeven maken, alleen die mysql_data_seek($rsBetalingen,0) doet het hem. Maar met een do-while moet je op twee plaatsen mysql_fetch_assoc gebruiken (een keer voor de lus en een keer in de conditie), vandaar de vraag waarom je dat doet, maar dat komt dus door Dreamweaver (?).
Dat komt inderdaad door dreamweaver, hij geeft het zo aan. Maar ik vind het ook veel logischer vat jullie zeggen, vandaar dat ik er een while van heb gemaakt.
Wat ik doe: ik kijk of die nummers gelijk zijn aan elkaar. Dit is niet bij test, maar als de overschrijvingNR in de tbl_Overschrijvingen zit (die records bevat afkomstig van de bank) dan is de overschrijving gebeurd.
Ik heb even opgezocht hoe het zit met een join en wat ik dus moet doen volgens jou: 1 alles recordrs eruit halen wanneer tbl_kampDeelnemer.overschrijvingsNR = tbl_Overschrijvingen.overschrijvingsNR en die joinen met tbl_kampDeelnemer.overschrijvingsNR != tbl_Overschrijvingen.overschrijvingsNR ? Dat moet ik straks eens proberen. Dat moet inderdaad lukken en dan kan ik filteren door gewoon het 1ne deel van de join te gebruiken of het andere deel. (betaald / niet betaald)

Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 01:20

MueR

Admin Tweakers Discord

is niet lief

Dan zal ik het maar weggeven:
PHP:
1
while ($row_rsNaam = mysql_fetch_assoc($rsNaam));

Die ";" verkliert elke vorm van loop. Die do..while statement gaat altijd maar 1 keer worden uitgevoerd.

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • Sp33dFr34k
  • Registratie: Juni 2006
  • Niet online

Sp33dFr34k

Retro-Geek

Raynman schreef op zaterdag 23 januari 2010 @ 11:24:
Maar met een do-while moet je op twee plaatsen mysql_fetch_assoc gebruiken (een keer voor de lus en een keer in de conditie), vandaar de vraag waarom je dat doet, maar dat komt dus door Dreamweaver (?).
Dit wist ik dus niet, vandaar dat ik aangaf dat die regels overbodig waren. Maargoed, ik gebruik dan ook altijd gewoon een while loopje, ziet er wat netter uit imo en het is korter.

Verder wist ik ook niet dat Dreamweaver php code kan genereren, weet ik dat ook weer.. 8)7

i7 9700k + Be-Quiet Dark Rock 4 Pro | Gigabyte Z390 Aorus Ultra | Gigabyte RTX5070Ti | Samsung 970 Pro 512GB + 860 EVO 1TB + 860 QVO 4TB | 2x8GB DDR4 3000Mhz | Seasonic Platinum 660W | Fractal Design R6 | Samsung Oddyssey G7 Neo | Edifier M60


Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 01:20

MueR

Admin Tweakers Discord

is niet lief

Sp33dFr34k schreef op zaterdag 23 januari 2010 @ 14:09:
Verder wist ik ook niet dat Dreamweaver php code kan genereren, weet ik dat ook weer.. 8)7
Vergeet het ook maar direct weer. Gegenereerde code is bijna altijd ruk :p

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • silentkiller
  • Registratie: Februari 2003
  • Laatst online: 19-09 08:06
Dan hebben we allemaal weer wat geleerd :)
Verder ben ik aan het prullen geweest met de joins:
code:
1
SELECT * FROM tbl_Kampdeelnemer LEFT JOIN tbl_Overschrijvingen ON tbl_Kampdeelnemer.overschrijvingnr = tbl_Overschrijvingen.overschrijvingnr INNER JOIN tbl_Lid USING (lidnummer) INNER JOIN tbl_Kamp USING (kampID) WHERE filters...

Hij laat dus alle kampdeelnemers zien (bedrag is ingevuld als ze betaalt hebben, NULL als ze niet betaald hebben) en ik kan door de inner joins ook de juiste groep / het juiste kamp aanspreken.

Bedankt jongens !

Acties:
  • 0 Henk 'm!

  • aaajeetee
  • Registratie: Augustus 2002
  • Laatst online: 18-09 12:49
MueR schreef op zaterdag 23 januari 2010 @ 13:41:
Dan zal ik het maar weggeven:
PHP:
1
while ($row_rsNaam = mysql_fetch_assoc($rsNaam));

Die ";" verkliert elke vorm van loop. Die do..while statement gaat altijd maar 1 keer worden uitgevoerd.
Bij een do-while moet er juist een ";" aan het eind van de while.

bron.

Acties:
  • 0 Henk 'm!

  • silentkiller
  • Registratie: Februari 2003
  • Laatst online: 19-09 08:06
Nog een klein vraagje: door de left join krijg ik alle waarden uit tbl_Kampdeelnemers te zien met hun bijhorende overschrijvingsnummer en bedrag uit tbl_overschrijvingen (zie screenshot)
Afbeeldingslocatie: http://www.tverdonck.be/table.png
Nu vroeg ik mij af of het mogelijk was om het overschrijvingsnummer overal te behouden (dus niet weergeven als NULL) maar het bedrag wel te weergeven als NULL als er niets in tbl_Overschrijvingen staat met dat overschrijvingsnummer

Concreet op het screenshot: In de 1ste kolom moeten de overschrijvingnrs blijven staan (allemaal), in de laatste kolom mogen enkel de bedragen staan die in tbl_Overschrijvingen voorkomen.

Ik kan het doen door telkens de overschrijvingnr op te halen met een nieuwe query adhv het lidnummer in tbl_Deelnemer maar dat lijkt me een beetje omslachtig.

Op het net vind ik niet direct een alternatief voor de join aangezien de left join perfect zijn werk doet in dit geval.

Edit:
code:
1
SELECT tbl_Kampdeelnemer.overschrijvingnr, lidnummer, bedrag, naam, tak FROM tbl_Kampdeelnemer LEFT JOIN tbl_Overschrijvingen ON tbl_Kampdeelnemer.overschrijvingnr = tbl_Overschrijvingen.overschrijvingnr INNER JOIN tbl_Lid USING (lidnummer) INNER JOIN tbl_Kamp USING (kampID)

Excuses :+

[ Voor 14% gewijzigd door silentkiller op 23-01-2010 15:19 ]

Pagina: 1