Toon posts:

[MySQL] met LEFT JOIN verkeerde results

Pagina: 1
Acties:

Verwijderd

Topicstarter
Voor een project ben ik bezig met php en mysql en ben ik met behulp van o.a. google tot onderstaande situatie uitgekomen waar ik even vastloop.

Even een schets van de situatie:

Ik heb 2 tabellen in mijn database: 'factuurgegevens' en 'betalingen'.
Tussen deze twee tabellen heb ik een relatie aangemaakt met het veld 'userid' in betalingen naar 'id' in 'factuurgegevens'.
In de tabel 'betalingen' worden, zoals de naam al aangeeft, betalingen toegevoegd.

Een voorbeeld van een betaling waarin 'userid' 6 een betaling heeft gedaan op 06-04-2007 over het jaar 2006:

id | datum | bladnmr | jaar | userid
12 | 06-04-2007 | blad1 | 2006 | 6

Nu heb ik een query gemaakt om alle users uit de database te halen welke betaald hebben over een bepaald jaar:

code:
1
2
3
4
5
SELECT factuur.id, factuur.naam, factuur.adres, factuur.huisnummer, factuur.postcode, factuur.plaats, factuur.categorie, betaal.jaar 
FROM factuurgegevens AS factuur 
LEFT JOIN betalingen AS betaal ON betaal.userid = factuur.id 
AND betaal.jaar ='.$_GET['jaar_1']
WHERE betaal.jaar != NULL


Deze query geeft de verwachte resultaten weer: alle users die betaald hebben in bijvoorbeeld het jaar 2007. Nu wil ik echter ook alle users tonen welke nog niet betaald hebben in een bepaald jaar.

code:
1
2
3
4
5
SELECT factuur.id, factuur.naam, factuur.adres, factuur.huisnummer, factuur.postcode, factuur.plaats, factuur.categorie, betaal.jaar
FROM factuurgegevens AS factuur
LEFT JOIN betalingen AS betaal ON betaal.userid = factuur.id
AND betaal.jaar !=2007
OR betaal.jaar = NULL


Deze query geeft ook de verwachte resultaten, behalve wanneer een user meerdere betalingen heeft gedaan. Ik krijg meerdere keren dezelfde userid terug, wat ik er uit filter in php. Alleen wanneer een user een betaling heeft gedaan, in bijvoorbeeld 2006 en 2007, wil ik dat deze niet in de resulaten voorkomen (hij of zij heeft immers betaald in 2007), maar deze komen nu wel in de resultaten voor.

Iemand hier die mij een duwtje in de goede richting kan geven?

  • Icelus
  • Registratie: Januari 2004
  • Niet online
Conditie klopt niet helemaal?
SQL:
1
2
3
4
5
6
   SELECT factuur.id, factuur.naam, factuur.adres, factuur.huisnummer,
          factuur.postcode, factuur.plaats, factuur.categorie, betaal.jaar
     FROM factuurgegevens AS factuur
LEFT JOIN betalingen AS betaal
       ON betaal.userid = factuur.id
      AND (betaal.jaar!=2007  OR  betaal.jaar IS NULL)

Developer Accused Of Unreadable Code Refuses To Comment


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Ik denk dat je zoiets niet eenvoudig met een join op kan lossen. Ik zou het met een subselect proberen:

SQL:
1
2
3
4
5
6
7
SELECT factuur.id, factuur.naam, factuur.adres, factuur.huisnummer,
   factuur.postcode, factuur.plaats, factuur.categorie
FROM factuurgegevens AS factuur 
WHERE
  factuur.id NOT IN (SELECT b.userid FROM betalingen b WHERE b.jaar = 2007)
-- OF een equivalente not-exists:
  NOT EXISTS (SELECT * FROM betalingen b WHERE b.jaar = 2007 AND b.userid = factuur.id)

Verwijderd

Topicstarter
Icelus schreef op vrijdag 06 april 2007 @ 10:38:
Conditie klopt niet helemaal?
SQL:
1
2
3
4
5
6
   SELECT factuur.id, factuur.naam, factuur.adres, factuur.huisnummer,
          factuur.postcode, factuur.plaats, factuur.categorie, betaal.jaar
     FROM factuurgegevens AS factuur
LEFT JOIN betalingen AS betaal
       ON betaal.userid = factuur.id
      AND (betaal.jaar!=2007  OR  betaal.jaar IS NULL)
Inderdaad, die heeft me weer een stuk op weg geholpen :D!

Nu kan het alleen nog zijn dat wanneer er meerdere betalingen zijn toegevoegd, ik dus ook meerdere keren hetzelfde userid terug krijg. Dit los ik op dit moment op de volgende manier op:

PHP:
1
2
3
4
5
6
7
8
9
10
11
     $userid = 0;
     while($row = mysql_fetch_array($result)
     {
          //kijken of vorige userid hetzelfde is
          if($userid != $row['id'])
          {
               //userid is niet hetzelfde -> user tonen
               echo $row['id'];
          }
          $userid = $row['id'];         
     }


Is dit op te lossen in de query zelf? Dit omdat ik bang bent dat wanneer er resultaten moeten worden getoond met meer dan 1000+ records het allemaal een beetje traag gaat worden, of is dit te verwaarlozen? Ik post dit nog maar even in dit topic, omdat ik het niet echt relevant vind om er een nieuw topic voor te openen.

edit:
ACM schreef op vrijdag 06 april 2007 @ 11:00:
Ik denk dat je zoiets niet eenvoudig met een join op kan lossen. Ik zou het met een subselect proberen:

SQL:
1
2
3
4
5
6
7
SELECT factuur.id, factuur.naam, factuur.adres, factuur.huisnummer,
   factuur.postcode, factuur.plaats, factuur.categorie
FROM factuurgegevens AS factuur 
WHERE
  factuur.id NOT IN (SELECT b.userid FROM betalingen b WHERE b.jaar = 2007)
-- OF een equivalente not-exists:
  NOT EXISTS (SELECT * FROM betalingen b WHERE b.jaar = 2007 AND b.userid = factuur.id)
Deze werkt ook perfekt. Krijg het alleen nog niet werkend dat ook de id's getoond worden uit de tabel 'factuurgegevens' die nog geen record(s) hebben in de tabel 'betalingen'.

[ Voor 22% gewijzigd door Verwijderd op 06-04-2007 12:08 ]


  • Icelus
  • Registratie: Januari 2004
  • Niet online
Verwijderd schreef op vrijdag 06 april 2007 @ 11:07:
[...]


Inderdaad, die heeft me weer een stuk op weg geholpen :D!

Nu kan het alleen nog zijn dat wanneer er meerdere betalingen zijn toegevoegd, ik dus ook meerdere keren hetzelfde userid terug krijg. Dit los ik op dit moment op de volgende manier op:

PHP:
1
2
3
4
5
6
7
8
9
10
11
     $userid = 0;
     while($row = mysql_fetch_array($result)
     {
          //kijken of vorige userid hetzelfde is
          if($userid != $row['id'])
          {
               //userid is niet hetzelfde -> user tonen
               echo $row['id'];
          }
          $userid = $row['id'];         
     }


Is dit op te lossen in de query zelf? Dit omdat ik bang bent dat wanneer er resultaten moeten worden getoond met meer dan 1000+ records het allemaal een beetje traag gaat worden, of is dit te verwaarlozen? Ik post dit nog maar even in dit topic, omdat ik het niet echt relevant vind om er een nieuw topic voor te openen.
Als je iedere gebruiker maar een keer wilt tonen kun je GROUP BY gebruiken:
SQL:
1
2
3
4
5
6
   SELECT factuur.id
     FROM factuurgegevens AS factuur
LEFT JOIN betalingen AS betaal
       ON betaal.userid = factuur.id
      AND (betaal.jaar!=2007  OR  betaal.jaar IS NULL)
 GROUP BY factuur.id
Het klopt dat factuur.id een gebruikers-ID is?

Developer Accused Of Unreadable Code Refuses To Comment