Ouwe rakker |
|
Dit topic is ter documentatie van een vraag die gesteld is op de Chat van Sitemasters.
De bezoeker had een database met daarin twee tabellen waarvan hij data wilde relateren. Deze tabellen waren client en behandeling (SQL).
Het idee was om een overzicht te maken van alle cliënten met daar tevens de vermelding in van de laatste behandeling die de cliënt had gekregen. Natuurlijk diende er rekening gehouden te worden met de volgende zaken:
* Een cliënt kan nog geen behandelingen hebben gehad
* Een cliënt kan reeds meerdere behandelingen hebben gehad
Wanneer een INNER JOIN/LEFT OUTER JOIN wordt toegepast, dan zal in verband met de interne werking van MySQL, het eerst matchende record worden opgehaald. Wanneer we dus een JOIN doen tussen client en behandeling, dan krijgen we in principe de eerste behandeling terug die de client heeft gevolgd.
Wanneer we gebruik maken van een GROUP BY en proberen met MAX() te werken voor de datum van een behandeling, dan krijgen we inderdaad de meest recente datum naar boven. We krijgen dan echter niet de naam van de meest recente behandeling, want hier is de MAX() niet op toegepast (en die zou hier ook geen relevant effect op hebben).
Er is uiteindelijk gekozen voor onderstaande query. We maken hierbij een temp table aan met daarin de informatie uit de originele tabel, maar we hebben hierbij de afspraken aflopend gesorteerd op datum. Wanneer de JOIN dus nu het eerste record matched, dan is dit dus de meest recente behandeling. Gezien de LEFT OUTER JOIN komen ook de cliënten zonder behandelingen naar voren, waarbij de kolommen genomen uit de temp table de NULL waarde bevatten, wat we gewend zijn van een OUTER JOIN.
Het enige onderdeel wat later nog toegevoegd moest worden is de GROUP BY. Bij het uitvoeren van de query zonder deze clausule zagen we dat wanneer er meerdere rijen voor één cliënt bestaan in de behandelingen tabel, er alsnog meerdere rijen voor die ene cliënt gereturned worden. Dit houdt dus in dat we alsnog cliënten meerdere malen zouden krijgen, welgeteld het aantal keren dat zij een behandeling hebben ondergaan.
SELECT
c.id_client, c.naam_client, c.voornaam_client, b.naam_beh, b.datum_beh, COUNT(naam_beh) AS aantal_behandelingen
FROM
client AS c
LEFT OUTER JOIN
(
SELECT id_client, naam_beh, datum_beh
FROM behandeling
ORDER BY datum_beh DESC
) AS b
ON c.id_client = b.id_client
GROUP BY id_client
SELECT c.id_client, c.naam_client, c.voornaam_client, b.naam_beh, b.datum_beh, COUNT(naam_beh) AS aantal_behandelingen FROM client AS c LEFT OUTER JOIN ( SELECT id_client, naam_beh, datum_beh FROM behandeling ORDER BY datum_beh DESC ) AS b ON c.id_client = b.id_client GROUP BY id_client
|