Left outer join doet het niet

Status
Niet open voor verdere reacties.

BartSt

Gebruiker
Lid geworden
26 jun 2012
Berichten
86
Dames en heren,

Hierbij vinden jullie de SQL instructie van mijn query.
Ik wil een oplijsting van alle ziektedagen per medewerker. Elke actieve, eigen medewerker moet op de lijst voorkomen, ook als die geen ziektedagen heeft. Ik dacht dat dit precies de opzet was van een left outer join.

Het resultaat is echter anders. Het lijkt erop dat ik enkel mensen krijg die ziek zijn geweest, en mensen die dit jaar nog helemaal geen afwezigheid hebben gehad (verlof, recup, ...). Mensen die afwezig maar niet ziek zijn geweest, krijg ik niet te zien.

Wat loopt er mis?

Code:
PARAMETERS [Geef jaar (yyyy)] Short;
SELECT WN_Persoonsgegevens.Rijksregisternummer, WN_Persoonsgegevens.Naam, WN_Persoonsgegevens.Voornaam, WN_Afwezigheden.Begindatum, WN_Afwezigheden.Einddatum, Year([Begindatum]) AS Jaar, WN_Afwezigheden.Aantal, WN_Afwezigheden.Opmerking
FROM (WN_Persoonsgegevens LEFT JOIN WN_Afwezigheden ON WN_Persoonsgegevens.Rijksregisternummer = WN_Afwezigheden.Rijksregisternummer) LEFT JOIN WN_Tewerkstellingen ON WN_Persoonsgegevens.Rijksregisternummer = WN_Tewerkstellingen.Rijksregisternummer
WHERE (((Year([Begindatum]))=[Geef jaar (yyyy)]) AND ((WN_Persoonsgegevens.[Datum uit dienst]) Is Null Or (WN_Persoonsgegevens.[Datum uit dienst])>Now()) AND ((WN_Tewerkstellingen.Contract) Is Null Or (WN_Tewerkstellingen.Contract)<>"Extern") AND ((WN_Afwezigheden.Afwezigheid) Like "Ziekte" Or (WN_Afwezigheden.Afwezigheid) Is Null))
ORDER BY WN_Persoonsgegevens.Naam;
 
Dat ligt er volgens mij aan waar het kolommetje [Begindatum] vandaan komt, indien uit WN_Persoonsgegevens is er volgens mij niks aan de hand en zou je query goed moeten zijn, indien deze uit een van de JOIN tabellen komt dien je nog een OR [Begindatum] IS NULL in je query te verwerken
 
Bedankt voor je reactie. Ik heb je advies gevolgd, maar helaas blijft het resultaat hetzelfde. Nieuwe SQL:
(Ik heb naast het toevoegen van de "Is Null" de datumselectie aangepast.)

Code:
PARAMETERS [Welk jaar? (YYYY)] Short;
SELECT WN_Persoonsgegevens.Rijksregisternummer, WN_Persoonsgegevens.Naam, WN_Persoonsgegevens.Voornaam, WN_Afwezigheden.Begindatum, WN_Afwezigheden.Einddatum, WN_Afwezigheden.Aantal, WN_Afwezigheden.Opmerking
FROM (WN_Persoonsgegevens LEFT JOIN WN_Afwezigheden ON WN_Persoonsgegevens.Rijksregisternummer = WN_Afwezigheden.Rijksregisternummer) LEFT JOIN WN_Tewerkstellingen ON WN_Persoonsgegevens.Rijksregisternummer = WN_Tewerkstellingen.Rijksregisternummer
WHERE (((Year([WN_Afwezigheden].[Begindatum]))<=[Welk jaar? (YYYY)] Or (Year([WN_Afwezigheden].[Begindatum])) Is Null) AND ((Year([WN_Afwezigheden].[Einddatum]))>=[Welk jaar? (YYYY)] Or (Year([WN_Afwezigheden].[Einddatum])) Is Null) AND ((WN_Persoonsgegevens.[Datum uit dienst]) Is Null Or (WN_Persoonsgegevens.[Datum uit dienst])>Now()) AND ((WN_Tewerkstellingen.Contract) Is Null Or (WN_Tewerkstellingen.Contract)<>"Extern") AND ((WN_Afwezigheden.Afwezigheid) Like "Ziekte" Or (WN_Afwezigheden.Afwezigheid) Is Null))
ORDER BY WN_Persoonsgegevens.Naam;
 
Zonder een voorbeeldje (liefst in 2003 format, dan kan ik er zo nog naar kijken) wordt het een beetje lastig gokken. Maar ik snap je NULL check niet helemaal. Bij een Outer Join heb je één tabel waarvan je alle record(gegeven)s wilt zien ([WN_Persoonsgegevens]) en één of meer tabellen die aan elkaar gelinked zijn, die dus een LEFT of RIGHT join krijgen. In jouw geval maak je twee outer joins, waarvan ik mij afvraag of die met [WN_Tewerkstellingen] wel nodig is. Deze tabel is namelijk aan [WN_Persoonsgegevens] gekoppeld, en ik neem toch aan dat je in [WN_Tewerkstellingen] van elke werknemer wel gegevens hebt opgeslagen, want je houdt de contractgegevens niet bij in [WN_Persoonsgegevens], dus zou je van elke werknemer minstens één record in [WN_Tewerkstellingen] moeten hebben. Die koppeling kan dan gewoon een INNER JOIN zijn.

Bij een Outer Join met [WN_Afwezigheden] zie je dus van alle medewerkers uit [WN_Persoonsgegevens] data staan, en van personen waarvan je in [WN_Afwezigheden] geen record hebt, blijven de velden leeg. Je kunt dus de NULL controle ook doen (en misschien wel beter) op het veld [WN_Afwezigheden].[Rijksregisternummer]. Zowiezo zou ik de NULL check niet op de functie YEAR doen, maar rechtstreeks op het datumveld. Dat is namelijk al NULL.
 
Michel,

Ik heb nav je antwoord de joins gewijzigd, echter zonder gunstig resultaat. In bijlage vind je een testversie van mijn DB in 2003 formaat. Ik heb die in een rar- en vervolgens in een zip-bestand moeten steken om het te kunnen uploaden.

Bekijk bijlage 2012-07-24 Test query ziekte2.zip

Merk op dat persoon met nummer 0...01 afwezig is geweest, maar niet ziek. Die belandt niet in mijn query, terwijl ik dat wel verwacht.
 
Laatst bewerkt:
Ik denk niet dat het (op een makkelijke manier althans) binnen één query kan, omdat je eigenlijk twee tegenstrijdige selecties moet maken. Ik zou dus met een UNION query werken op basis van een query die de ziekte records selecteert, en een query die een query met dezelfde velden maakt voor de personen zonder ziekterecords. Die queries zien er dan zo uit:

Afwezigheden_ZIEK:
Code:
PARAMETERS [Welk jaar? (YYYY)] Short;
SELECT WN_Persoonsgegevens.Rijksregisternummer, WN_Persoonsgegevens.Naam, WN_Persoonsgegevens.Voornaam, WN_Afwezigheden.Begindatum, WN_Afwezigheden.Einddatum, WN_Afwezigheden.Aantal, WN_Afwezigheden.Opmerking, WN_Afwezigheden.Afwezigheid
FROM (WN_Persoonsgegevens LEFT JOIN WN_Afwezigheden ON WN_Persoonsgegevens.Rijksregisternummer = WN_Afwezigheden.Rijksregisternummer) INNER JOIN WN_Tewerkstellingen ON WN_Persoonsgegevens.Rijksregisternummer = WN_Tewerkstellingen.Rijksregisternummer
WHERE (((WN_Afwezigheden.Afwezigheid)="Ziekte") AND ((Year([WN_Afwezigheden].[Begindatum]))<=[Welk jaar? (YYYY)] Or (Year([WN_Afwezigheden].[Begindatum])) Is Null) AND ((Year([WN_Afwezigheden].[Einddatum]))>=[Welk jaar? (YYYY)] Or (Year([WN_Afwezigheden].[Einddatum])) Is Null) AND ((WN_Persoonsgegevens.[Datum uit dienst]) Is Null Or (WN_Persoonsgegevens.[Datum uit dienst])>=Date()) AND ((WN_Tewerkstellingen.Contract) Is Null Or (WN_Tewerkstellingen.Contract)<>"Extern") AND ((WN_Tewerkstellingen.Einddatum) Is Null Or (WN_Tewerkstellingen.Einddatum)>=Now()))
ORDER BY WN_Persoonsgegevens.Rijksregisternummer;

Afwezigheden_Niet_Ziek:
Code:
SELECT WN_Persoonsgegevens.Rijksregisternummer, WN_Persoonsgegevens.Naam, WN_Persoonsgegevens.Voornaam, Null AS Begindatum, Null AS Einddatum, Null AS Aantal, Null AS Opmerking, Null AS Afwezigheid
FROM WN_Persoonsgegevens INNER JOIN WN_Tewerkstellingen ON WN_Persoonsgegevens.Rijksregisternummer = WN_Tewerkstellingen.Rijksregisternummer
WHERE (((WN_Persoonsgegevens.Rijksregisternummer) Not In (SELECT Rijksregisternummer FROM Afwezigheden_ZIEK)) AND ((WN_Tewerkstellingen.Contract) Is Null Or (WN_Tewerkstellingen.Contract)<>"Extern") AND ((WN_Tewerkstellingen.Einddatum) Is Null Or (WN_Tewerkstellingen.Einddatum)>=Date()))
ORDER BY WN_Persoonsgegevens.Rijksregisternummer;

UNION Query:
Code:
SELECT Afwezigheden_ZIEK.Rijksregisternummer AS RegisterNummer, Afwezigheden_ZIEK.Naam, Afwezigheden_ZIEK.Voornaam, Afwezigheden_ZIEK.Begindatum, Afwezigheden_ZIEK.Einddatum, Afwezigheden_ZIEK.Aantal, Afwezigheden_ZIEK.Opmerking, Afwezigheden_ZIEK.Afwezigheid
FROM Afwezigheden_Niet_Ziek, Afwezigheden_ZIEK 
UNION SELECT Afwezigheden_Niet_Ziek.Rijksregisternummer AS RegisterNummer, Afwezigheden_Niet_Ziek.Naam, Afwezigheden_Niet_Ziek.Voornaam, Afwezigheden_Niet_Ziek.Begindatum, Afwezigheden_Niet_Ziek.Einddatum, Afwezigheden_Niet_Ziek.Aantal, Afwezigheden_Niet_Ziek.Opmerking, Afwezigheden_Niet_Ziek.Afwezigheid 
FROM Afwezigheden_Niet_Ziek
ORDER BY RegisterNummer;
 
Michel,

Goed idee! Het werkt. Weer eens bedankt voor je hulp :)
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan