Autor Zpráva
Fury
Profil *
Zdravím,

poprosil bych o vás o radu, navrhuji strukturu db (mysql) pro web, kde bych chtěl zobrazovat fotbalové výsledky + statistiky týmů. Tzn. že ke každému zápasu bych chtěl ukládat statistiky jednotlivých hráčů:
- odehrané minuty
- v jaké minutě vstřelil branku
- v jaké minutě obdržel žlutou/červenou kartu

Napadla mě tato varianta, ale narážim tam na problém:


Jsem schopný tam ukládat do statistik hráče a co provedl, v tabulce statistiky_typ bude "žlutá karta", "červená karta", "gól", ale moc nevím, jak se statistikami odehraných minut? Ukládat do jiné tabulky? Chtěl bych totiž pak zobrazovat výpis hráčů, kde bude souhrn žlutých/červených karet, gólů a odehraných minut.

Díky moc za radu
RastyAmateur
Profil
Fury:
Do statistiky_typ můžeš přidat odehrane_minuty a do sloupce "minuta" v tabulce "statistiky" si dáš ten počet. V PHP už to pak zpracuješ jednoduše.
Je spoustu řešení...
Fury
Profil *
RastyAmateur:
Díky, to je taky možnost.

Ale ještě mě napadlo, kdybych chtěl ukládat info ohledně toho, kdy ten hráč střídal. Tzn. potřebuju rozlišovat tyhle stavy:

hráč hrál v základu a nestřídal
hráč hrál v základu a vystřídal (např. v 60. minutě)
hráč nastoupil v průběhu - např. v 60. minutě, tzn. odehrál 30. minut
hráč byl je na lavičce

jak řešit toto?

Díky moc
RastyAmateur
Profil
Fury:
Myslím si, že by to mohlo jít stejným způsobem... Jen na to střídání bude potřeba vytvořit tedy více záznamů v statistiky_typ (1 pro hrál v základu a nestřídal, 1 pro hrál v základu střídal, 1 pro nastoupil v průběhu apod...), přičemž až na konci každého zápasu budeš vše zadávat do formuláře, nastavíš si v PHP script, který ti vypočte, kolik hrál hráč celkem minut...
Keeehi
Profil
Máš tabulku událostí, tak to neznásilňuj počtem odehraných minut. Budeš mít kromě karet a gólů už jen 2 události - hráč přišel na hřiště a hráč odešel ze hřiště. A s tím vyrobíš kompletní statistiku počtu odehraných minut a střídání. Když bude hráč hrát celý zápas tak bude mít příchod v 0 a odchod v 90. Když bude začínat a pak bude v 72 minutě vystřídán, bude mít příchod v 0, odchod v 72 a ten co ho bude střídat bude mít příchod v 72 a odchod v 90. No a doba strávená na hřišti je jednoduše odchod - příchod.

Taky by bylo řešení mít karty zvlášť v tabulce, góly taky zvlášť a počet odehraných minut taky zvlášť. Těm minutám by to prospělo nejvíce. Protože doba strávená na hřišti by se dala lehce vypočítat už v databázi.
Fury
Profil *
Keeehi:
Díky, takže jestli to dobře chápu, zachovám tabulku "statistiky_typ" a tam budu mít záznamy:
- žlutá karty
- červená karta
- gól
- hráč nastoupil
- hráč střídal

Je to tak? Jen přemýšlím, že pokud bych chtěl ukládat i hráče, kteří nenastoupili? Tak přidám další záznam "hráč na lavičce"?


Ještě jeden dotaz, mám např. tým FC Praha, který bude mít družstva A i B, jak toto řešit? Vytvořit si tabulku "tymy_hlavni", kde bude hlavní název týmu, tzn. "FC Praha" a pod tím bude tabulka "tymy", kam přidám ještě sloupec "hlavni_tym_id"? Nebo jde to řešit nějak elegantněji?

Díky moc za pomoc
Keeehi
Profil
statistiky_typ
- žlutá karta
- červená karta
- gól
- hráč přišel na hřiště
- hráč odešel ze hřiště

Soupisku do vlastní tabulky.
Soupiska
- id
- id_zapas
- id_hrac

Kdo seděl na lavičce je ten, kdo je na soupisce ale nemá statistiku_typ - hráč přišel na hřiště
Fury
Profil *
Keeehi:
Tzn. ale že budu mít 2x skoro stejný záznamy, protože min. 11 záznamů budu mít vždy v tabulce statistiky a stejně tak i v soupisce. Je to určitě vhodný řešení? Díky
Keeehi
Profil
Fury:
Je to určitě vhodný řešení?
Ano. Nejsou to úplně stejné záznamy. Ano, část by se dala dopočítávat ale nedoporučil bych to.
Kajman
Profil
Asi bych tabulku soupiska nedělal. Stačí přidat typ statistiky "Byl k dispozici na lavičce, ale nenastoupil."
Fury
Profil *
Akorát přemejšlim, když budu mít v tabulce statistiky následující záznamy:

INSERT INTO `statistiky` (`id`, `typ_id`, `hrac_id`, `zapas_id`, `minuta`, `info`) VALUES
(1, 4, 88052128, 98, 0, ''),
(2, 5, 88052128, 98, 90, ''),
(3, 4, 94041212, 98, 0, ''),
(4, 5, 94041212, 98, 90, ''),
(5, 4, 96091069, 98, 0, ''),
(6, 5, 96091069, 98, 90, '');

Jak pak vypočítám kolik odehrál daný hráč minut? Protože potom budu chtít např. na základě hráče vypočítávat počet minut z různých zápasů. Můžu ještě poprosit o radu?

Díky
TomášK
Profil
Pokud hráč střídal v zápase nejvýše jednou, pak takto:

SELECT 
  s2.minuta - s1.minuta
FROM
  statistiky s1
  JOIN statistiky s2 ON s1.zapas_id = s2.zapas_id AND s1.hrac_id = s2.hrac_id 
WHERE 
  s1.typ_id = 4 AND
  s2.typ_id = 5

Pár dalších postřehů:

Možná už je pozdě a něco přehlížím, ale víš ve tvém schématu, za který tým hráč hrál?

Tabulku se zápasy bych rozdělil na dvě:
zapasy(id, datum, soutez_id, sezona_id)
zapasy_tymy(id, zapas_id, tym_id, vysledek, domaci)
Budou se na tom lépe dělat statistiky typu 'nejvíc vstřelených branek'.


Zrušil bych statistiky_typ a udělal pro jednotlivé události své tabulky. Bude se to hodit, až budeš chtít přidat info, za co hráč tu kartu dostal.

Místo toho bych udělal tabulky
soupisky(id, hrac_id, zapasy_tymy_id)
karty(id, soupiska_id, minuta, zluta/cervena)
stridani(id, minuta, prisel_id, odesel_id)

Takto udělané střídání neumožní příchod hráče bez toho, aby někdo odešel. Není to černobílé, má to i své nevýhody. Zvaž, s čím se ti bude lépe pracovat.

Dotaz na délku působení na hříšti bude vypadat takto:

SELECT 
  soupisky.hrac_id,
  IFNULL(odchody.minuta, 90) - IFNULL(prichody.minuta, 0)
FROM
  soupisky
  LEFT JOIN stridani prichody ON prichody.prisel_id = soupisky.id
  LEFT JOIN stridani odchody ON odchody.odesel_id = soupisky.id

A stejně jako předchozí varianta selže, pokud bude hráč střídat několikrát. Na takovou situaci by to chtělo window funkce, které mysql myslím pořád neumí
Keeehi
Profil
TomášK:
A stejně jako předchozí varianta selže, pokud bude hráč střídat několikrát.
Což by mělo být v pohodě protože takovou možnost pravidla fotbalu nedovolují. Snad se nepletu, odborník na fotbal nejsem.
Fury
Profil *
Keeehi:
Přesně tak :).

TomášK:
Díky za postřehy, nakonec jsem se rozhodl dát do jedné tabulky statistiky jako góly a karty, to není potřeba rozlišovat a do druhé tabulky jsem se rozhodl dát střídání, jak si navrhnul ty.

Ale nechápu 2 věci:
1) proč máš zápasy na dvě tabulky? Proč je to lepší, než mít jednu tabulku: zapasy (id, datum, soutez_id, sezona_id, domaci_id, hoste_id, vysledek)

2) Proč ukládáš ještě zvlášť soupisku? Tyhle data přeci můžu vytáhnout z tabulky stridani, ne?

Díky moc
Kcko
Profil
Fury:
Podle toho co chceš provádět za statistiky.
1) Já mám např. takovouhle tabulku (podobnou strukturou) taky, nerozděluji to tak jak navrhl TomášK, záleží opět na to co z toho chceš dolovat.
2) A obecně, někdy může být lepší navrhnout tabulky lehce redundantně (tj, některá data se mohou opakovat) a to z důvodu snížení složitosti sql dotazů a celkově i zátěže.

Já vytvářel tabulky, kde jsem si data různě předpočítaval nebo dopočítaval a při změně např. zápasu jsem to celé opět přepočítaval a negeneroval za běhu jen pomocí SQL dotazu, ale sahal jsem si pro již připravená data v určité podobě, protože se to někdy do určitých výpisů z důvodu bodu 2 nehodilo. To uvidíš sám ... ( třeba Ti ukážu tuhle tabulku fifa.gameway.cz/historicka-tabulka :))


A jinak k bodům 1,2 viz níže exporty tabulek a nějaké screenshoty z mého fotbalového webu.
Třeba Ti to nějak pomůže.

CREATE TABLE IF NOT EXISTS `zapasy_sestavy` (
  `zapasID` mediumint(9) NOT NULL,
  `hracID` mediumint(9) NOT NULL,
  `tymID` mediumint(9) NOT NULL,
  `soutezID` mediumint(9) NOT NULL,
  `sezonaID` mediumint(9) NOT NULL,
  `poziceIndex` smallint(6) NOT NULL,
  KEY `zapasID` (`zapasID`,`hracID`,`tymID`,`soutezID`,`sezonaID`),
  KEY `zapasID_2` (`zapasID`),
  KEY `hracID` (`hracID`),
  KEY `tymID` (`tymID`),
  KEY `soutezID` (`soutezID`),
  KEY `sezonaID` (`sezonaID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;


CREATE TABLE IF NOT EXISTS `zapasy_statistika_hraci` (
  `zapasID` mediumint(9) NOT NULL,
  `soutezID` mediumint(9) NOT NULL,
  `sezonaID` mediumint(9) NOT NULL,
  `fazeID` mediumint(9) NOT NULL,
  `tymID` mediumint(9) NOT NULL,
  `hracID` mediumint(9) NOT NULL,
  `minut` tinyint(4) NOT NULL,
  `hracIn` tinyint(4) NOT NULL,
  `hracOut` tinyint(4) NOT NULL,
  `golyHra` tinyint(4) NOT NULL,
  `golyPen` tinyint(4) NOT NULL,
  `golyVlastni` tinyint(4) NOT NULL,
  `zk` tinyint(4) NOT NULL,
  `ck` tinyint(4) NOT NULL,
  `cisteKonto` tinyint(4) NOT NULL,
  `golyDostal` tinyint(4) NOT NULL,
  `vyloucenMinuta` tinyint(4) NOT NULL,
  `resultFlag` enum('NA','V','R','P','KV','KP','KK') NOT NULL,
  `teamGF` tinyint(4) NOT NULL COMMENT 'Branky co tym obdrzel v zakl. dobe',
  `teamGA` tinyint(4) NOT NULL COMMENT 'Branky co tym obdrzel',
  KEY `zapasID` (`zapasID`),
  KEY `hracID` (`hracID`),
  KEY `minut` (`minut`),
  KEY `tymID` (`tymID`),
  KEY `soutezID` (`soutezID`),
  KEY `sezonaID` (`sezonaID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


CREATE TABLE IF NOT EXISTS `statistika` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `zapasID` mediumint(9) NOT NULL,
  `soutezID` mediumint(9) NOT NULL,
  `sezonaID` mediumint(9) NOT NULL,
  `fazeID` smallint(6) NOT NULL,
  `hracID` mediumint(9) NOT NULL,
  `tymID` mediumint(9) NOT NULL,
  `akceID` tinyint(4) NOT NULL,
  `minuta` decimal(5,2) NOT NULL,
  `poziceIndex` smallint(6) NOT NULL,
  PRIMARY KEY (`ID`),
  KEY `zapasID_2` (`zapasID`),
  KEY `soutezID` (`soutezID`),
  KEY `sezonaID` (`sezonaID`),
  KEY `fazeID` (`fazeID`),
  KEY `hracID` (`hracID`),
  KEY `tymID` (`tymID`),
  KEY `akceID` (`akceID`)
) ENGINE=InnoDB AUTO_INCREMENT=15703 DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;


Screenshoty statistik:



TomášK
Profil
Fury:
> proč máš zápasy na dvě tabulky? Proč je to lepší, než mít jednu tabulku: zapasy (id, datum, soutez_id, sezona_id, domaci_id, hoste_id, vysledek)

Pro porovnání třeba dotaz na nejvyšší počet vstřelených gólů:

SELECT MAX(vysledek) FROM zapasy_tymy
vs
SELECT GREATEST(MAX(domaci_vysledek), MAX(hoste_vysledek)) FROM zapasy

Není to lepší, jen jiné. Některé dotazy se v tom píšou líp, některé hůř. Dotaz, který z mé struktury udělá tu tvou, používá JOINy, z tvé struktury na mou je to UNION. Mám raději ten JOIN, tuším tam lepší práci s indexy, bez záruky.

Fury:
> 2) Proč ukládáš ještě zvlášť soupisku? Tyhle data přeci můžu vytáhnout z tabulky stridani, ne?

Do tabulky střídání bych dal jen pokud někdo opravdu vystřídal. Abys mohl vytáhnout i soupisky, musel bys tam mít informaci, že hráči v základu v 0. minutě střídali na plochu, hráči na lavičce střídali na lavičku. Šlo by to, ale přijde mi to uměle vykonstruované, neintuitivní. V budoucnu třeba budeš chtít uložit číslo hráče, co má na zádech. To už do střídání nepatří.

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: