Autor Zpráva
TomášK
Profil
V jedne hre se konaji turnaje, na kazdy prijede nekolik hracu. Z turnaju se na konci sezony spocita kvalfikace - na zaklade umisteni na jednotlivych turnajich. Primarnim kriteriem pro razeni kvalfikace jsou body (umim spocitat, neni podstatne jak), dalsim kriteriem pak nejlepsi umisteni na turnaji (tj ten kdo vyhral aspon turnaj bude pred tim, kdo skoncil nejlepe druhy), v pripade, ze maji stejne nejlepsi umisteni na turnaji, bere se druhe nejlepsi umisteni, pokud i to je stejne, treti nejlepsi umisteni atd. (a tu je zakopany pes). Lze pocitat s tim, ze vsichni hraci sehrali stejny pocet turnaju, ale nevime kolik to bylo (tj neni to konstanta, kterou bychom vedeli predem).
K dispozici mam tabulku
poradi(hrac, turnaj, poradi) - umisteni hrace na turnaji
SELECT 
hrac,
SUM(poradi) AS body, -- pouze priklad, ve skutecnosti se body pocitaji sloziteji
FROM 
poradi
GROUP BY hrac
ORDER BY body, ...?
bohyn
Profil
TomášK
Subdotazdy a secist kazde umisteni zvlast.

SELECT 
hrac,
SUM(poradi) AS body, 
(SELECT count(t1.hrac) FROM body AS t1 WHERE t1.hrac = hrac AND t1.poradi = 1) AS prvni,
(SELECT count(t2.hrac) FROM body AS t2 WHERE t2.hrac = hrac AND t2.poradi = 2) AS druhy,
(SELECT count(t3.hrac) FROM body AS t3 WHERE t3.hrac = hrac AND t3.poradi = 3) AS treti
FROM 
poradi
GROUP BY hrac
ORDER BY body DESC, prvni DESC, druhy DESC, treti DESC
TomášK
Profil
Tohle nedělá přesně, co chci - zohledňuje to jen umístění na prvních třech místech. Zkusím svůj dotaz upřesnit na příkladu.
Mám tři turnaje, osoby Aleš, Bob, Cyril a Dan, a pár dalších, kteří nás nezajímají, naši vyvolení se na turnajích umístili takto:
Aleš: 1. místo, 10 místo a 20. místo
Bob: 2. 20. 20.
Cyril: 1. 15. 25.
Dan: 1. 10. 15.
(seřadil jsem to podle nejlepších umístění, neznamená to, že na jednom turnaji byli tři hráči první :) )

Předpokládejme, že mají v kvalifikaci stejně bodů. Chtěl bych, aby je to seřadilo v tomto pořadí:
Dan: 1. 10. 15. (při porovnávání s Alešem má stejné nejlepší umístění, stejné druhé nejlepší, ale lepší třetí)
Aleš: 1. 10. 20.
Cyril: 1. 15. 25.
Bob: 2. 20. 20.

Ale turnaje nemusí být tři, ale kldině čtyři, osm, dvacet...
Kajman_
Profil *
Rychlé to nebude, ale možná by šlo něco na způsob
group_concat(lpad(poradi,8,0) order by poradi)
TomášK
Profil
Kajman_: Dík, funguje. Tohle bylo to, co jsem se snažil vymyslet a ne a ne na to přijít. Rychlost není až tak důležitá, vzhledem k tomu, že se tak řadí nejvýš stovky záznamů. Group_concat asi podceňuju a oni s ním jdou občas dělat zajímavé triky :)

Při nočním přemýšlení mě napadlo ještě další řešení, které tu zanechávám budoucím generacím:
Předpokládejme pro jednoduchost, že ve zdrojové tabulce máme ještě sloupec, který nám určuje, kolikáté nejlepší umístění hráče to je, tj.
Aleš: 1. místo, 10 místo a 20. místo
bude v tabulce jako
(hrac, poradi, nejlepsi_umisteni, turnaj)
('Ales', 1, 1, nejaky_turnaj)
('Ales', 10, 2, nejaky_turnaj)
('Ales', 20, 3, nejaky_turnaj)
Pokud by tam nebyl, lze ho vytvořit i v dotazu, ale pro zjednodušení to nedělám.

SELECT 
     hrac, 
     primarni_kriterium, 
     pomocne_body
FROM (
    -- spocitame primarni kriterium 
    SELECT
            hrac,
            SUM(poradi) AS primarni_kriterium
        FROM 
         poradi
    ) AS primarni_kriterium

    -- doplnime o druhe kriterium, ktere nam hrace seradi podle nejlepsich umisteni
   -- LEFT JOIN, nebot druhe kriterium pocitame jen pro hrace, kteri maji s nekym stejne primarni kriterium
   LEFT  JOIN (
        SELECT
            hrac,
            SUM(body) AS pomocne_body
        FROM 
        (
            SELECT 
                a.hrac,
                IF(MIN(a.poradi) < MIN(b.poradi),1,0) AS body
            FROM 
                poradi AS a 
                JOIN poradi AS b 
                -- join na tabulku s primarnimi kriteriem, abychom druhe kriterium pocitali jen tehdy, kdyz je primarni kriterium stejne
                JOIN ( SELECT hrac, SUM(poradi) AS primarni_kriterium FROM poradi) AS pk_a ON pk_a.hrac = a.hrac
                JOIN ( SELECT hrac, SUM(poradi) AS primarni_kriterium FROM poradi) AS pk_b ON pk_b.hrac = b.hrac
            WHERE 
                a.hrac != b.hrac AND
                a.nejlepsi_umisteni = b.nejlepsi_umisteni AND
                a.poradi != b.poradi AND 
                pk_a.primarni_kriterium = pk_b.primarni_kriterium
            GROUP BY a.hrac,b.hrac
        ) AS t
        GROUP BY hrac
    ) AS pomocne_kriterium
ORDER BY primarni_kriterium, body DESC
     



V poddotazupro každou dvojici hráčů A,B, kteří mají stejné primární kritérium, sestavím tabulku, kde bude na řádku umístění hráče A na jeho n-tém nejlepším turnaji a umístění hráče B na jeho n-tém nejlepším turnaji. Z té si pomocí GROUP BY vyberu první turnaj, kde se liší a pokud je na tom hráč A lépe, dostane bod (to dělá IF(MIN(a.poradi) < MIN(b.poradi),1,0)). Poté ve vnejším dotazu sečtu tyto pomocné body pro každého hráče (jedná se o cosi jako body ze "vzájemných zápasů", nenapadá mě výstižnější pojmenování), setřídím tabulku podle primárního kritéria a podle pomocných bodů.

Oproti Kajmanovu řešení je to o něco čistší - neporovnávám řetězce, o mnoho složitější (na řádek to prostě není:) ). Zdá se mi, že by to mohlo být rychlejší, ale skálopevně přesvědčen o tom nejsem.
bohyn
Profil
A to funguje? Ja treba nenasel kde se bere "pk.hrac".
TomášK
Profil
Máš pravdu, je to tam špatně, má tam být jednou pk_a, podruhé pk_b - opravil jsem to. Přímo tenhle dotaz jsem nezkoušel, ale dělám jeho obdobu pro svoje data, v principu je to dobře - ale potřebuje ještě vychytat mouchy. Co najdu v průběhu psaní svého dotazu, to opravím.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

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