[SQL] Query wordt soms niet goed uitgevoerd

Pagina: 1
Acties:

  • TweakersOnly
  • Registratie: September 2000
  • Laatst online: 20:46
Voor een schoolopdracht moet ik een SQL-query maken, die alle contracten, die een medewerker met medewerkernummer 13 in de maand mei 2002 bij een bedrijf heeft, moet teruggeven.

Hiervoor is benodigd de tabel contract. In deze tabel wordt het medewerkerID bijgehouden en wordt alleen de begindatum van dat contract bijgehouden, de einddatum is overbodig.

De query die ik nu heb, is:
code:
1
2
3
4
5
6
7
8
SELECT * FROM Contract 
WHERE MedewerkerID = 13 
AND Begindatum <= #06/01/2002# 
AND Begindatum >= 
     (SELECT Max(Begindatum) FROM Contract 
    WHERE MedewerkerID = 13 
    AND Begindatum <= #05/01/2002#) 
ORDER BY Begindatum

Wanneer een medewerker voor het begin van de maand nog geen contracten heeft, dan loopt de query dus spaak. Ik heb echter nog geen andere oplossing kunnen vinden. :(

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

waar is die subquery voor nodig :?
Maand mei selecteren is toch gewoon:
where datum '1 mei' and '1 juni'

:?

  • TweakersOnly
  • Registratie: September 2000
  • Laatst online: 20:46
Op dinsdag 14 mei 2002 18:40 schreef ACM het volgende:
waar is die subquery voor nodig :?
Maand mei selecteren is toch gewoon:
where datum '1 mei' and '1 juni'

:?
Een contract kan op willekeurige dag van het jaar ingaan. In principe kan een medewerker in de maand mei dus 31 verschillende contracten hebben. :)

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Op dinsdag 14 mei 2002 18:46 schreef TweakersOnly het volgende:
Een contract kan op willekeurige dag van het jaar ingaan. In principe kan een medewerker in de maand mei dus 31 verschillende contracten hebben. :)
Owja :)

Dan moet je dus kijken of de einddatum en de begindatum samen de maand mei overspannen en/of een dag ervan...
Is idd niet zo'n fijne query ;)

  • TweakersOnly
  • Registratie: September 2000
  • Laatst online: 20:46
Op dinsdag 14 mei 2002 18:47 schreef ACM het volgende:

[..]

Owja :)

Dan moet je dus kijken of de einddatum en de begindatum samen de maand mei overspannen en/of een dag ervan...
Is idd niet zo'n fijne query ;)
De einddatum mag dus niet in de tabel worden opgenomen. :( De begindatum van een contract = de einddatum van een vorig contract (indien aanwezig) dus overbodige gegevens. :(

  • JaQ
  • Registratie: Juni 2001
  • Laatst online: 23:46

JaQ

Je query wordt in beginsel
select *
from contracten
where datum between <<start_date>> and <<end_date>>

let dan wel even op je datumformaat (dus gebruik trunc of een to_date met tijdaanduiding in een Oracle database).

Je probleem is echter dat je eerste contract een startdatum van voor het begin van de periode kan hebben (als ik het goed heb). Overlap dus.

Het selecteren van het laatste contract dat voor de periode valt heb je (soms) ook nodig:
select *
from contracten
where datum = (select max (datum)
from contracten
where datum < <<start_date>>)


Je wherestatement heeft dus een uitbreiding nodig die zegt:
als mijn eerste datum van een contract in de periode na de startdatum van de periode valt, dan heb ik het laatste contract dat voor de startdatum van de periode valt ook nodig.

Het complete statement wordt dan iets als:

select *
from contracten
where datum between <<start_date>> and <<end_date>>
union
select *
from contracten
where <<start_date>> > ( select min (datum)
from contracten
where datum > <<start_date>> )
and datum = (select max (datum)
from contracten
where datum < <<start_date>>)
order by datum.


Of maak ik nou een rare denkkronkel?

/* offtopic
het is inderdaad waar dat redundante gegevens niet opgenomen horen te worden, maar in de praktijk gebeurd dat wel om queries als deze te voorkomen i.v.m. performance issues. */

Egoist: A person of low taste, more interested in themselves than in me


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Op dinsdag 14 mei 2002 19:24 schreef DrFrankenstoner het volgende:
/* offtopic
het is inderdaad waar dat redundante gegevens niet opgenomen horen te worden, maar in de praktijk gebeurd dat wel om queries als deze te voorkomen i.v.m. performance issues. */
Sterker nog, in veel situaties kunnen contracten prima overlappen en daardoor zou ik einddata liever _wel_ opslaan.

  • TweakersOnly
  • Registratie: September 2000
  • Laatst online: 20:46
Het was een schoolopdracht waarin duidelijk stond dat de einddatum niet mag worden opgeslagen. Anders was de query ook een eitje geweest. ;)

  • TweakersOnly
  • Registratie: September 2000
  • Laatst online: 20:46
DrFrankenstoner, you're the man. :) :)

De juiste query moet zijn:
code:
1
2
3
4
5
6
7
8
9
10
11
SELECT * FROM Contract
WHERE MedewerkerID = 13
AND Begindatum between #05/01/2002# AND #06/01/2002#
UNION
SELECT * FROM Contract
WHERE MedewerkerID = 13
AND Begindatum = 
     (SELECT max(Begindatum) FROM Contract
     WHERE MedewerkerID = 13
     AND Begindatum < #05/01/2002#)
ORDER BY Begindatum

Thanx. *D

  • Goodielover
  • Registratie: November 2001
  • Laatst online: 18-08 11:34

Goodielover

Only The Best is Good Enough.

Eigenlijk zou je het als volgt moeten verwoorden:
Geef mij alle contracten waarvoor geldt dat de begindatum voor 1 juni ligt en er niet een contract is met een latere begindatum en waarvoor ook geldt dat de begindatum voor (of op) 1 mei ligt. DUS:
code:
1
2
3
4
5
6
7
8
9
10
SELECT *
FROM   Contract c1
WHERE  c1.MedewerkerID = 13
AND    c1.Begindatum < #06/01/2002#
and    not exists 
    (SELECT 1
     FROM   Contract c2
     WHERE  c2.MedewerkerID = = c1.MedewerkerID
     AND    c2.Begindatum >  c1.Begindatum
     AND    c2.Begindatum <= #01/05/2002#

Dit is de beste oplossing. Hij is lastig te begrijpen, maar klopt wel
Pagina: 1