Autor Zpráva
Casero
Profil
Dobrý večer,
dělám statistiky badmintonových zápasů, které jsou uloženy v tabulce zapasy:
Struktura
hrac1_id, hrac2_id, set1_hrac1,set1_hrac2,set2_hrac1,set2_hrac2,set3_hrac1,set3_hrac2
Nebo znáte lepší způsob zápisu zápasu do db?

dále pak mám tabulku hraci:
Struktura
nick, id

A snažím se vytáhnout skore každého hráče, počet zápasů atd...
Samozřejmě by to šlo přes dva dotazy, první vybere hrače a druhý statistiky...ale kvůli různému seřazování statistik je to nevhodné.
Ovšem můj způsob vytvoření 1 dotazu je nešikovný, jelikož nelze vytáhnout jedním poddotazem více sloupců, což je logické.
Můj SQL:
 
select h.nick,
(SELECT sum(if(hrac1_id=h.id,set11+set21+set31,set12+set22+set32)) 
FROM `zapasy` 
WHERE hrac1_id=h.id or hrac2_id=h.id) as dal,
(SELECT sum(if(hrac1_id=h.id,set12+set22+set32,set11+set21+set31))   
FROM `zapasy` 
WHERE hrac1_id=h.id or hrac2_id=h.id) as dostal 
from hraci h 
order by dal


A tímto způsobem bych musel stále přidávat další a další poddotaz. Proto bych se chtěl zeptat, zda existuje nějaký lepší způsob? Přemýšlel jsem o nějakém zgrupování, ale nic jsem nevymyslel, jak by to šlo provést. :(
Předem mockrát děkuji za rady
TomášK
Profil
Sloupce pojmenované neco1, neco2,... znamenají téměř vždy nevhodnou strukturu databáze. Nejinak v
tomhle případě.

Tabulka hraci zustane (id, nick).

Dál bych vytvořil tabulky
zapasy(id, info o zapasu) -- tahle tabulka ani není potřeba, pokud nejsou k zápasu žádné informace
sety(id, zapas_id, hrac_id, set, cislo_hrace) -- cislo_hrace je 1 pro začínajícího, 2 pro druhého

Dotaz třeba na počet zápasů hráče se smrskne na:
SELECT 
    hrac_id, 
    COUNT(*) AS pocet_zapasu
FROM 
    (SELECT hrac_id, zapas_id FROM sety GROUP BY hrac_id, zapas_id)
GROUP BY hrac_id;

Nelíbí se mi tam dvakrát GROUP BY, ale lepší varianta mě nenapadá.
Kajman_
Profil *
Při původní struktuře by to mohlo být

select t.hrac_id, sum(t.dal) dal, sum(t.dostal)
from (
(select hrac1_id hrac_id, sum(set11)+sum(set21)+sum(set31) dal, sum(set12)+sum(set22)+sum(set32) dostal from zapasy group by hrac1_id)
union all
(select hrac2_id hrac_id, sum(set12)+sum(set22)+sum(set32) dal, sum(set11)+sum(set21)+sum(set31) dostal from zapasy group by hrac2_id)
) t
group by t.hrac_id


V té nové struktuře by to šlo jedním group by díky count(distinct zapas_id).
Casero
Profil
TomášK
Tato nová struktura vypadá chytře no. Jako kolik bodů dal je snadné, ale kolik dostal je celkem fuška. Najit ty správné protějšky. :(

Kajman_
Děkuji. Pěkné. :) Ale asi ta nová struktura je krok kupředu.
Kajman_
Profil *
Co udělat ty sety jako
id_zapasu, cislo_setu, body1, body2
a zápasy jako
id_zapasu, hrac1, hrac2, datum a tak

Union my mohl být na statistiky rychlejší než join k hledání bodů soupeře ve stejném setu, ale to jen jen domněnka.
TomášK
Profil
Casero

Možná ne až tak strašná jak na pohled vypadá (v návrhu jsem zapomněl sloupec body):
SELECT 
    hrac_id, 
    SUM(sety > sety_soupere) AS pocet_vyher
    SUM(sety < sety_soupere) AS pocet_proher
    SUM(sety) AS pocet_vyhranych_setu
    SUM(sety_soupere) AS pocet_prohranych_setu
FROM (
    SELECT 
        hrac_id,
        SUM(sety1.body > sety2.body) AS sety
        SUM(sety1.body < sety2.body) AS sety_soupere
    FROM
        sety AS sety1
        JOIN sety AS sety2 ON sety1.zapas_id = sety2.zapas_id AND sety1.set = sety2.set AND idsety1.cislo_hrace != sety2.cislo_hrace
    GROUP BY hrac_id, zapas_id
    ) AS duely
GROUP BY
    hrac_id


Kajman_
Pokud jde o rychlost, pak nedokážu odhadnout. Pokud jde o složitost dotazů, pak si myslím, že při mé struktuře budou většinou jednodušší. Mám pocit, že při tvé struktuře budou dotazy plné hrac1 = 42 OR hrac2 = 42 a UNIONu, které budou využívat ten samý kód jen s 2 místo 1. Ale pokud by se to ukázalo jako významně rychlejší, asi by to za to stálo.

Jen pro představu - využívám podobnou strukturu, jako jsem popsal, jen zápasy nejsou rozdělené na sety - každý z hráčů uhraje v zápase určitý počet bodů. Dotaz na největší vítězství (nejvyšší rozdíl bodů v zápase) trvá při cca 50 000 zápasech několik sekund. Předpokládám, že výhledově přejdu na databázi, která umí indexy nad funkcemi (pokud nezjistím, že to MySQL už umí/bude umět), což by ten dotaz zřejmě zkrátilo na několik ms.

Edit: doplnil jsem podmínky do JOINu, dík za upozornění
Kajman_
Profil *
Ve spojení setů ješte chybí zapas_id a set. V téhle struktuře bych se možná přiklonik k redundatním údajům. Rovnou příznak přidat 0,1, zda set či zápas vyhrál. Nebudou se muset dělat porovnání < > a bude stačit sum, nebou cont-sum... a vlastně se ani nebudou muset hledat soupeři (pokud se nebude hledat součet míčků soupeřů), takže by to mohlo významně pomoci serveru.
Casero
Profil
TomášK
Naprosto nádherné. Hned si s tím jdu hrát. Mockrát děkuji.

Kajman_
Také mockrát děkuji.
Toto téma je uzamčeno. Odpověď nelze zaslat.