Hej! Först måste du plocka ut det bästa betyget för varje klass och sedan det lägsta datumet detta uppnåddes. Jag gjorde det första i en subselect som du ser i exemplet nedan. I subselecten finns en max-function som viktar betygen så att MVG är värt mest och 'G' minst. Om du har fler betgsnivåer får du lägga till dem här alternativt bryta ut dem och lägga dem i en tabell för extra flexibilitet. Det löste det hela! Dessvärre var jag för snabb med att deklarera problemet löst... Tror jag löst det nu. Opps! Se där! Givetvis ska det vara så. Det gick nog lite för fort när jag skrev koden :)SQL: Hitta högsta betyg vid tidigaste datum för varje kurs
Nu har jag (ännu en gång!) kört fast i något som känns som om det borde vara väldigt enkelt...
Jag har genom diverse UNIONS och joinar plockat ut ett resultatset som ger följande kolumner:
Kurskod|Betyg|Datum
Resultatsetet saknar primärnyckel och det är fullt möjligt att dubbletter förekommer. Jag vill nu plocka ut det högsta betyget för respektive kurskod och vid vilket datum detta nåddes. Om samma högsta betyg nåtts för samma kurskod flera gånger, ska det bara returneras den rad som innehåller det tidigaste datum det högsta betyget uppnåddes.
Om jag har raderna:
1|VG|2003-01-01
1|MVG|2003-02-02
1|MVG|2003-03-03
2|G|2003-04-04
2|G|2003-05-05
ska alltså följande returneras:
1|MVG|2003-02-02
2|G|2003-04-04
Idéer? Känns som sagt som att det borde vara enkelt, men...
MVH
/JonasSv: SQL: Hitta högsta betyg vid tidigaste datum för varje kurs
Lycka till! //Johan
DECLARE @Betyg TABLE
(
KursKod int,
BetygKod varchar(3),
Datum smalldatetime
)
INSERT INTO @Betyg VALUES(1,'VG','2003-01-01')
INSERT INTO @Betyg VALUES(1,'MVG','2003-02-02')
INSERT INTO @Betyg VALUES(1,'MVG','2003-03-03')
INSERT INTO @Betyg VALUES(2,'G','2003-04-04')
INSERT INTO @Betyg VALUES(2,'G','2003-05-05')
SELECT KursKod = b.KursKod,
BetygKod = b.BetygKod,
Datum = Min(b.Datum)
FROM @Betyg b
INNER JOIN ( SELECT KursKod,
BetygKod = CASE Max(CASE BetygKod WHEN 'MVG' THEN 2 WHEN 'G' THEN 1 END) WHEN 2 THEN 'MVG' WHEN 1 THEN 'G' ELSE 'FEL' END
FROM @Betyg b
GROUP BY KursKod
) sub ON
sub.BetygKod = b.BetygKod
GROUP BY b.KursKod, b.BetygKod
ORDER BY KursKodSv: SQL: Hitta högsta betyg vid tidigaste datum för varje kurs
Stort tack Johan, jag hade verkligen fastnat i en felaktig tankebana.
Nu återstår bara att optimera den gigantiska query som plockar fram de tre kolumnerna... ...men det är en annan historia.
Tack än en gång!
MVH
/JonasSv: SQL: Hitta högsta betyg vid tidigaste datum för varje kurs - funkar tyvärr
Följande tabell returneras helt utan förändring:
Kurs|Betyg|Datum
74 1 2004-11-04 15:38:40.363
75 1 2004-11-04 15:38:40.363
75 2 2003-04-16 11:56:47.000
78 1 2004-11-04 15:38:40.363
78 2 2003-04-16 11:56:47.000
78 3 2004-06-11 13:51:39.000
Obs att betyget i verkligheten alltså anges med ett numeriskt ID, och att jag därför hoppade över Case-satsen. Den förvandlades alltså till:
<code>...BetygKod = MAX(BetygKod)...</code>
Men det kan väl inte vara problemet? Verkar snarare vara joinen.
Lägg märke till att tiden för den överflödiga raden för kurs 75 är identisk med kurs 74:s tid, som också är kurs 74:s högsta betyg/tidigaste tillfälle. Alla tidpunkter som är tidigaste tidpunkt vid högsta betyg för *vilken kurskod somhelst* kommer alltså med även för övriga kurskoder, förutsatt att även de kurskoderna faktiskt betygssatts vid den tidpunkten också.
Fler förslag? Jag har vridit och vänt på detta ett par timmar nu och är helt klart för kass på SQL för att fixa det.
MVH
/JonasSv: SQL: Hitta högsta betyg vid tidigaste datum för varje kurs
Ändrade:
<code>... sub ON
sub.BetygKod = b.BetygKod
GROUP BY...</code>
Till:
<code>... sub ON
sub.BetygKod = b.BetygKod AND sub.KursKod = b.KursKodKod
GROUP BY...</code>
Och det verkar väl rimligt.
Skulle inte kommit dit utan Johans hjälp, tack igen!
mvh
/JonasSv: SQL: Hitta högsta betyg vid tidigaste datum för varje kurs
//J