Autor Zpráva
jboob
Profil
Dobrý den, chtěl jsem Vás požádat o radu pro amatéra začátečníka.
Mám tabulku obsahující statistická data atletických disciplín. Tabulka obsahuje řadu údajů, ale zejména
jméno, id_zavodnika, disciplina, výkon (např čas), body. Potřeboval bych udělat select, který
by vybral výkony v jedné disciplíně a seřadil je podle bodové hodnoty (tady si rady vím )

SELECT * FROM vykony WHERE disciplina='100m' ORDER BY body ASC limit 1,50

bez problému mi vypíše prvních 50 výkonů, teď bych ale potřeboval do výsledku zahrnout pro každého zavádníka
dle bodů jen jeho nejlepší výkon a tady si nevím rady

Díky za pomoc
Keeehi
Profil
SELECT MAX(body), id_zavodnika FROM vykony WHERE disciplina='100m' GROUP BY id_zavodnika LIMIT 1,50
Moderátor juriad: Omlouvám se; myslel jsem, že píší svůj příspěvek.
juriad
Profil
Ještě doplním to řazení:
SELECT MAX(body), id_zavodnika
FROM vykony
WHERE disciplina='100m'
GROUP BY id_zavodnika
ORDER BY MAX(body) ASC 
LIMIT 1,50
jboob
Profil
díky za radu, bohužel to nějak nefunguje. Podle všeho se zdá, že GROUP BY nejprve vybere první výskyt id_zavodnika (chronologicky ja byl do tabulky vložen je jich tam několik set tisíc) a teprve potom setřídí podle ORDER BY


napadlo mě podle nějakého článku jestli by nebyl řešením nějaký vnořený dotaz, nejprve setřídit a pak vybrat MAX(body), ale nevím jak na to
juriad
Profil
jboob:
GROUP BY zařídí, že se pro každé id_zavodnika vytvoří skupinka se všemi záznamy dané hodnoty. Z těch se pak vybere jeden reprezentant. Pokud bys neuvedl agregační funkci, tak se vybere náhodně, v praxi to bude ten první. Tady je explicitně zmíněna MAX, takže se pro každého id_zavodnika vyberou maximální body. A podle nich se to nakonec seřadí.

Pokud chceš vybrat i nějaké dalši sloupce, je skutečně nutné provést poddotaz. Napíšu ho.
Alphard
Profil
Jak přesně máte napsaný ten dotaz? Váš popis neodpovídá teorii. Group by seskupuje na základě svých parametrů a z této skupiny vybírá maximum. Ty dotazy co vám kolegové napsali musí fungovat, ale nemůžete si k nim přidat další sloupce nepodléhající seskupení.

Pro řazení skupin viz Některé časteji řešené dotazy pro MySQL - FAQ » Nalezení posledních pěti článků z každé kategorie.
juriad
Profil
SELECT v.*
FROM vykony v
JOIN (
  SELECT MAX(body) maximum, id_zavodnika
  FROM vykony
  WHERE disciplina='100m'
  GROUP BY id_zavodnika
) n ON v.id_zavodnika = n.id_zavodnika AND v.body = n.maximum
ORDER BY body ASC
LIMIT 1, 50

Toto, ale má problém, pokud závodník měl v několika pokusech stejné body. To se pak musí řešit dalším poddotazem a je potřeba nějaký identifikátor identifikátor záznamu, který jsi zatím buď zatajil nebo prostě v tabulce neexistuje.
jboob
Profil
do výsledku potřebuji dostat i další sloupce, např. jméno, klub, hodnotu výkonu


omlouvám se, že ještě jednou obtěžuji. Zkusi jsem aplikovat, ale prohlížeč mi píše chybu SQL

SELECT v.* 
   FROM stat v 
   JOIN (
      SELECT MAX(body) maximun, id_os 
      FROM stat 
      WHERE (druh='H' and pohl='1' and pkat=0 and trim(dis)='100m') 
      GROUP BY id_os 
      ) n ON v.id_os = n.id_os AND v.body = n.maximum 
    ORDER BY body ASC 
    limit 1, 50

Moderátor juriad: Vkládej prosím kódy mezi značky [pre] a [/pre] (stačí kliknout na ).
juriad
Profil
Máš tam překlep: maximun
jboob
Profil
Ještě jednou díky za radu, již je to snad OK.
Závěrem bych měl na Vás pánové ještě jeden malý dotaz. Mohli by jste mi doporučit nějakou vhodnou literaturu
pro samouky již pokročilého věku, kde bych se mohl s touto problematikou hlouběji a srozumitelně, nejlépe v češtině,
hlouběji obeznámit?
Díky
jboob
Profil
juriad
dobrý den, omlouvám se, že ještě jednou obtěžuji, ale narazil jsem na ještě jedenu komplikaci.
Je možné, že by v některých případech script vynechal ve výsledku první záznam?
Děkuji
juriad_
Profil *
Ano. To dělá ta 1 u LIMIT:
In other words, LIMIT row_count is equivalent to LIMIT 0, row_count.
To co jsi napsal vrátí 2. - 51. záznam.
jboob
Profil
Díky
jboob
Profil
Vážení zkušenější kolegové, díky Vám se mi podařilo udělat co jsem chtěl a statistický web sportovních výkonů vcelku funguje tak jak chci.
Potřeboval bych ale vyřešit ještě jeden problém. Pokud na výběr nejlepšího výkonu každého závodníka v určitém období použiji následující dotaz

SELECT v.* 
   FROM stat v 
   JOIN (
      SELECT MAX(body) maximun, id_os 
      FROM stat 
      WHERE (druh='H' and pohl='1' and pkat=0 and trim(dis)='100m' and datum between  pod and pdo) 
      GROUP BY id_os 
      ) n ON v.id_os = n.id_os AND v.body = n.maximum 
    ORDER BY body ASC 
    limit 0, 50
 

tak pokud některý ze závodníků zaplaval nejlepší výkon (s nejmenším časem) vícekrát, vypíše se vícekrát, místo pouze jednou
a to bez ohledu na zadané období.
Mohu poprosit ještě jenou o radu co s tím?

Díky
Kajman
Profil
Jaký je v tabulce stat primární klíč?
jboob
Profil
Kajman:
primární klič jsou body
Kajman
Profil
To by pak max(body) přeci nemohlo nikdy najít dvě stejné hodnoty. Primární klíč bude jiný.
jboob
Profil
Kajman:
jo omlouvám se, primární klič je na ID, na kterém je i auto increment
Kajman
Profil
Např. to můžete ještě jednou zgroupovat a najít nejstarší záznam, podle id...

SELECT s.*
FROM   stat s
       JOIN (SELECT Min(v.id) firstid
             FROM   stat v
                    JOIN (SELECT Max(body) maximun,
                                 id_os
                          FROM   stat
                          WHERE  ( druh = 'H'
                                   AND pohl = '1'
                                   AND pkat = 0
                                   AND Trim(dis) = '100m'
                                   AND datum BETWEEN pod AND pdo )
                          GROUP  BY id_os) n
                      ON v.id_os = n.id_os
                         AND v.body = n.maximum
                         AND v.druh = 'H'
                         AND v.pohl = '1'
                         AND v.pkat = 0
                         AND Trim(v.dis) = '100m'
                         AND v.datum BETWEEN v.pod AND v.pdo
             GROUP  BY v.id_os) f
         ON s.id = f.firstid
ORDER  BY body ASC, id
LIMIT  0, 50  

Edit: ke správné funkčnosti bude asi potřeba vyhledávací podmínky uvést 2x (na některých jiných databázích s analytickými funkcemi, by se to psalo lépe).
jboob
Profil
díky za radu. bohužel se mi zatím nedaří.

$sql="SELECT s.*
FROM   pl_stat s
       JOIN (SELECT Min(v.id) firstid
             FROM pl_stat v
                    JOIN (SELECT Min(cas_sec) minimun,
                                 id_os
                          FROM   pl_stat
                          WHERE  pohl = '1'
                                 AND Trim(dis) = '100 M' 
                          GROUP  BY id_os) n
                      ON v.id_os = n.id_os
                         AND v.cas_sec = n.minimum
                         AND v.pohl = '1'
                         AND Trim(v.dis) = '100 M'
             GROUP  BY v.id_os) f
         ON s.id = f.firstid
ORDER  BY cas_sec ASC, id

LIMIT  0, 50 ";

můžete mi poradit kde dělám chybu?
Díky.
Kajman
Profil
Asi jste nechal můj překlep v aliasu... minimun => minimum. Byl to jen takový nástřel.

Případně si vypište chybu, s ní najdete chybu v syntaxi i sám.

Vaše odpověď

Mohlo by se hodit

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: