Autor Zpráva
Fury
Profil *
Zdravím,

mám dotaz do DB, kde vytahuji TOP 5 hráče dle odehraných minut:
select 
    h.id,
    h.jmeno,
    sum(minut_celkem) as pocet_minut,
    n1.url url_hrace
from 
    statistiky_stridani ss
left join 
    hraci h on h.id = ss.hrac_id
left join
    navigace n1 on n1.id = h.nav_id
left join
    zapasy z
        on z.id = ss.zapas_id
left join
    souteze s
        on s.id = z.soutez_id
where
    s.rocnik_id = (select max(id) from rocnik) 
group by 
    ss.hrac_id
order by 
    pocet_minut desc, h.id asc    
limit 5

A potřeboval bych tam napojit i za který tým ten hráč hraje, ale vzhledem k tomu, že hráč může hrát za víc než jeden tým, potřebuji tam zobrazit u něj ten tým, za který odehrál nejvíc minut, což zvládnu tímto dotazem:
            SELECT
                ss.hrac_id,
                ss.tym_id,
                sum(minut_celkem),
                t.nazev
            FROM
                statistiky_stridani ss
            left join
                zapasy z
                    on z.id = ss.zapas_id
            left join
                souteze
                    s on s.id = z.soutez_id
            left join
                tymy t
                    on t.id = ss.tym_id
            WHERE
                s.rocnik_id = (select max(id) from rocnik) and ss.hrac_id = ID_HRÁČE
            group by 
                ss.hrac_id, ss.tym_id
            order by 
                ss.hrac_id asc  

Snažil jsem se to přes join nebo přes where propojit, ale nedaří se mi to správně. Mohu vás poprosit o radu? Případně pokud by bylo potřeba něco blíž vysvětlit, dejte vědět.

Díky moc
juriad
Profil
Fury:
On totiž ten druhý dotaz nevrací žádné maximum.
Zkusil jsem vytvořit pár view, která zjednodušují práci.
Podle mě nikdy nechceš LEFT JOIN.

Pozor na: „Before MySQL 5.7.7, the SELECT statement cannot contain a subquery in the FROM clause.“ (zdroj)

CREATE VIEW hrac_rocnik_minuty # pro každého hráče a ročník vrátí odehrané minuty
AS
  SELECT ss.hrac_id, s.rocnik_id, SUM(minut_celkem) AS pocet_minut
  FROM statistiky_stridani ss
  JOIN zapasy z ON z.id = ss.zapas_id
  JOIN souteze s ON s.id = z.soutez_id
  GROUP BY ss.hrac_id, s.rocnik_id

CREATE VIEW hrac_rocnik_tym_minuty # pro každého hráče, ročník a tým vrátí odehrané minuty
AS
  SELECT ss.hrac_id, s.rocnik_id, ss.tym_id, SUM(minut_celkem) AS pocet_minut
  FROM statistiky_stridani ss
  JOIN zapasy z ON z.id = ss.zapas_id
  JOIN souteze s ON s.id = z.soutez_id
  GROUP BY ss.hrac_id, s.rocnik_id, ss.tym_id

CREATE VIEW hrac_rocnik_tym # pro každého hráče a ročník vrátí tým, za který odehrál nejvíce minut
AS
  SELECT htrm.hrac_id, hrtm.rocnik_id, MIN(hrtm.tym_id) AS tym_id # pokud je shoda vezmeme tým s nižším id
  FROM hrac_rocnik_tym_minuty hrtm
  JOIN ( # pro každého hráče a ročník najde maximální počet minut, který hrál za nejaký tým
    SELECT hrac_id, rocnik_id, MAX(pocet_minut) max_minut
    FROM hrac_tym_rocnik_minuty
    GROUP BY hrac_id, rocnik_id
  ) hrm ON hrtm.hrac_id = hrm.hrac_id AND hrtm.rocnik_id = hrm.rocnik_id AND hrtm.pocet_minut = hrm.max_minut
  GROUP BY htrm.hrac_id, hrtm.rocnik_id # kvůli tomu, že mohl odehrát stejný počet minut za několik různých týmů

# samotný dotaz je pak jednoduchý:
SELECT h.id, h.jmeno, hrm.pocet_minut, n.url
FROM hraci h
JOIN (
  SELECT MAX(id) AS id
  FROM rocnik
) r
JOIN hrac_rocnik_minuty hrm ON hrm.hrac_id = h.id AND hrm.rocnik_id = r.id
JOIN hrac_rocnik_tym hrt ON hrt.hrac_id = h.id AND hrt.rocnik_id = r.id
JOIN tymy t ON t.id = hrt.tym_id
ORDER BY hrm.pocet_minut DESC, h.id ASC
LIMIT 5
Fury
Profil *
Díky moc, jen dva dotazy.

1) Mám mysql 5.6., dá se nějak obějít ta subquery?
2) Obecnej dotaz k pohledům, nikdy jsem s nima nepracoval, ale teď mám první projekt, kde pracuji s 10-100 tisíci záznamy a co se týče optimalizace, vyplatí se je vytvářet a pak o to dělat jednodušší dotazy?

Ještě jednou díky!
juriad
Profil
To omezení můžeš obejít dalším view, viz Object moved. Tedy řádky 22 - 24 budou definicí v novém view, které budeš připojovat namísto subquery.

Nevím, nemám tolik zkušeností. V každém případě to můžeš zkusit, je to otázka pár minut, pak budeš chytřejší a můžeš se pak s námi podělit.
Jakmile máš funkční dotaz s použitím view, můžeš ho vždy přepsat tak, aby je nepoužíval. V tomto případě bys pak mohl to filtrování na ročník přesunout někam hlouběji, aby se provedlo dříve.

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: