Avatar billede sbahn Nybegynder
07. december 2005 - 23:44 Der er 14 kommentarer og
1 løsning

Subquery bøvl

Mit indre query giver de ønskede resultater, men det ydre query returnerer kun en del af dem (5 poster). Hvorfor dog ?

SELECT DISCIPLINER.disciplinnavn, RESULTATER.displayscore FROM DISCIPLINER, RESULTATER WHERE DISCIPLINER.disciplinid=RESULTATER.disciplinid AND RESULTATER.personid=50 AND (DISCIPLINER.disciplinid, RESULTATER.score) IN (SELECT DISCIPLINER.disciplinid, MIN(RESULTATER.score) FROM DISCIPLINER, RESULTATER WHERE DISCIPLINER.disciplinid=RESULTATER.disciplinid AND RESULTATER.personid=50 GROUP BY DISCIPLINER.disciplinid) ORDER BY DISCIPLINER.disciplinid, RESULTATER.score;
Avatar billede Slettet bruger
09. december 2005 - 17:05 #1
For det første er det lidt lettere at overskue en så lang query, hvis man lige bryder den lidt op.

SELECT DISCIPLINER.disciplinnavn, RESULTATER.displayscore
  FROM DISCIPLINER, RESULTATER
WHERE DISCIPLINER.disciplinid=RESULTATER.disciplinid
  AND RESULTATER.personid=50
  AND (DISCIPLINER.disciplinid, RESULTATER.score) IN
      (
        SELECT DISCIPLINER.disciplinid, MIN(RESULTATER.score)
          FROM DISCIPLINER, RESULTATER
        WHERE DISCIPLINER.disciplinid=RESULTATER.disciplinid
          AND RESULTATER.personid=50
        GROUP BY DISCIPLINER.disciplinid
        )
ORDER BY DISCIPLINER.disciplinid, RESULTATER.score;

For det andet må du lige give et eksempel på, hvad den inderste giver, hvad den yderste giver, og hvad den yderste skulle have givet. Ellers er det ikke let at hjælpe, da vi andre jo ikke sidder med din database.
Avatar billede sbahn Nybegynder
12. december 2005 - 08:22 #2
Ja, det bliver da markant mere overskueligt. Tak.

Den samlede query giver

disciplinnavn    displayscore
50 m    7,00 sek.
60 m    8,00 sek.
Diskoskast (0,75 kg)    26,00 m
Diskoskast (1 kg)    25,25 m

Og den indre, kørt for sig selv,
Avatar billede sbahn Nybegynder
12. december 2005 - 08:26 #3
(disciplinid er erstattet af disciplinnavn for overskuelighedes skyld. Dette påvirker naturligvis ikke det ydre resultat)

disciplinnavn    MIN(RESULTATER.score)
50 m    7.000
60 m    8.000
80 m    10.770
100 m    13.120
200 m    27.220
600 m    109.300
800 m    172.700
1000 m    207.910
60 m hæk (76.2 cm, 6 hække, 11.75 / 7.65 / 10.00)    10.130
60 m hæk (84.0 cm, 5 hække, 13.00 / 8.50 / 13.00)    9.790
4x100 m    48.260
1000 m stafet    133.440
Længdespring (zone)    -4.840
Højdespring    -1.450
Stangspring    -2.700
Kuglestød (3 kg)    -10.970
Kuglestød (4 kg)    -11.060
Diskoskast (0,75 kg)    -26.000
Diskoskast (1 kg)    -25.250
Hammerkast (3 kg, 100 cm)    -24.150
Spydkast (400 g)    -32.930
Spydkast (600 g)    -39.980
Boldkast (250 g)    -33.360

Der er gode grunde til, at displayscore er en streng, mens score, der kan sorteres på, er et float. Og til at de begge findes. Nogle scores er negative (afhænger af disciplinen) for at voksende sortering kan benyttes på alle discipliner.
Avatar billede Slettet bruger
12. december 2005 - 08:58 #4
Måske det her kan bruges?

SELECT D1.disciplinnavn, R1.displayscore
  FROM DISCIPLINER as D1, RESULTATER AS R1
WHERE D1.disciplinid=R1.disciplinid
  AND R1.personid=50
  AND R1.score =
      (
        SELECT MIN(R2.score)
          FROM RESULTATER AS R2
        WHERE D1.disciplinid=R2.disciplinid
          AND R2.personid=50
        )
ORDER BY DISCIPLINER.disciplinid, RESULTATER.score;

Det er kraftigt inspireret af koden øverst på http://dev.mysql.com/doc/refman/4.1/en/example-maximum-column-group-row.html
Avatar billede sbahn Nybegynder
12. december 2005 - 21:03 #5
Det hjalp desværre ikke at give tabellerne et alias, men tak for hjælpen ikke desto mindre.
Avatar billede Slettet bruger
13. december 2005 - 06:46 #6
Kommer den stadig bare med de samme rækker?

Hvilken version af MySQL bruger du?

Og så lige for at sikre mig, at jeg har forstået det korrekt. Du ønsker at lave et udtræk for en person, der lister hans bedste resultat i alle de discipliner, han har deltaget i, korrekt?

Jeg kunne lige prøve at spørge min underviser idag, om han har en ide.
Avatar billede sbahn Nybegynder
13. december 2005 - 10:22 #7
1. Ja, output er uændret.
2. Jeg bruger (vist nok) version 5.
3. Det er nemlig lige netop det output, du beskriver, jeg ønsker.
Avatar billede sbahn Nybegynder
13. december 2005 - 22:54 #8
Jo, det var v5.
Kan nogen be- eller afkræte, hvorvidt det overhovedet er veldefineret at matche på flere kolonner fra subquerien
Avatar billede Slettet bruger
14. december 2005 - 05:40 #9
Hvis den giver samme resultat, som mit forslag, så må det jo virke, men du matcher jo kun (direkte) på en kolonne nu, eller hvad? Og der var jo også lidt mere i mit forslag, end bare anvendelsen af alias.

Og forskellen på den manualside, jeg linkede til og den tilsvarende manualside for MySQL 5.0 er, at på 5.0-siden står ikke andet end den kode, som jeg gik ud fra i 4.1-maualen. De andre metoder er altså forældede.

Men ellers findes der en metode mere, men det bliver lidt mere langhåret:

SELECT D1.disciplinnavn, R1.displayscore
  FROM DISCIPLINER AS D1
  JOIN RESULTATER as R1
      ON D1.disciplinid=R1.disciplinid
  LEFT JOIN RESULTATER AS R2
      ON R1.disciplinid=r2.disciplinid
      AND R1.score>R2.score
      AND R2.personid=50
WHERE R1.personid=50
  AND R2.score IS NULL
Avatar billede Slettet bruger
14. december 2005 - 05:42 #10
Og ja. Det er med vilje, at jeg brugte et større-end tegn. Det må ikke være et mindre-end, for så får du personens værste score i stedet.
Avatar billede sbahn Nybegynder
14. december 2005 - 21:44 #11
Ang. aliasforslaget, så vil det selvfølgelig ikke virke (efter hensigten) i den form, som du har skitseret det, da der mangler en "group by" i den indre forespørgsel. Er der ellers noget smart ved det?

Querien med et Left Join giver et tomt resultat, men det virker som om, at denne approach kan løse problemet, så nu roder jeg lidt md syntaksen.

I øvrigt: hvordan kan jeg finde ud af, hvilken version af mysql, jeg bruger?

Tak.
Avatar billede sbahn Nybegynder
14. december 2005 - 21:45 #12
Og angående det, jeg spurgte om tidligere, så er det særdeles veldefineret at matche på flere poster med flere rækker. Det hedder table subquery, og det er så langt, jeg er kommet:-)
Avatar billede Slettet bruger
15. december 2005 - 07:50 #13
Hvis du ser på den side, jeg henviste til fra manualen, vil du se, at der heller ikke er en group by - det burde ikke være nødvendigt, når vi kun selecter en aggregeret funktion, da den så tager for hele tabellen - dog med den udvælgelse der foretages med WHERE-sætningen.

Om den ene er smartere end den anden, kommer nok mest an på, hvad man er vant til at bruge.

Du kan prøve at bruge EXPLAIN på din query, så du kan se mere præcist, hvordan MySQL har tænkt sig at løse opgaven.
Avatar billede sbahn Nybegynder
15. december 2005 - 20:02 #14
Det foreslag, du gav for tre dage siden:

SELECT D1.disciplinnavn, R1.displayscore
  FROM DISCIPLINER as D1, RESULTATER AS R1
WHERE D1.disciplinid=R1.disciplinid
  AND R1.personid=50
  AND R1.score =
      (
        SELECT MIN(R2.score)
          FROM RESULTATER AS R2
        WHERE D1.disciplinid=R2.disciplinid
          AND R2.personid=50
        )
ORDER BY DISCIPLINER.disciplinid, RESULTATER.score;

virker perfekt! Jeg var bare meget skeptisk, fordi der manglede en group by. Nu vil jeg tage mig sammen til at forstå, hvad der egentlig foregår (for at forstå det, og fordi jeg har brug for en udvidelse).
Mange tak for hjælpen.
Avatar billede Slettet bruger
16. december 2005 - 08:40 #15
Ok, så vil jeg da lægge et svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester