Autor | Zpráva | ||
---|---|---|---|
Kcko Profil |
Ahoj,
mám následující kód na zobrazení tabulky tipéru (tipují na sportovní zápasy) Jediné co mě zajímá, zda-li by dotaz nešel zoptimalizovat, resp. jestli zvýrazněné části (v LEFT JOINU, které se připojují jako "tabulka") jsou správně, nejsem si jist zda-li jsem to spojil správně a jestli nevybírám větší část dat než je potřeba. Zkoušel jsem psát podmínku přímo pro konkrétního uživatele ale psalo mi to, že to nezná sloupeček. Něco ve smyslu WHERE soutez_id = %i AND user_id = t2.id Tak jsem to pak spojil tak jak to je nyní a je to funkční, vcelku rychlé (moc jsem to netestoval, je tam málo dat), ale stejně se mi to nepozdává. Díky public function getTabulka($soutezId) { return $rows = dibi::fetchAll(" SELECT t2.displayName, t2.id user_id, SUM(t3.status = 1 AND t3.vyherni = 1) tiketyVyherni, SUM(t3.status = 1) tiketyUkoncene, SUM(t3.status = 0) tiketyOtevrene, (10000 - IFNULL(tmp2.total, 0) + IFNULL(tmp3.total, 0)) kredit FROM users t2 JOIN ( SELECT DISTINCT t1.user_id FROM tip_users_tikety t1 JOIN users t2 ON t2.id = t1.user_id WHERE t1.soutez_id = %i ) tmp1 ON t2.id = tmp1.user_id JOIN tip_users_tikety t3 ON t3.user_id = t2.id LEFT JOIN ( SELECT SUM(vsazeno) total, user_id FROM tip_users_tikety WHERE soutez_id = %i GROUP BY user_id ) tmp2 ON tmp2.user_id = t2.id LEFT JOIN ( SELECT SUM(vyhra) total, user_id FROM tip_users_tikety WHERE soutez_id = %i AND vyherni = 1 GROUP BY user_id ) tmp3 ON tmp3.user_id = t2.id WHERE t3.soutez_id = %i GROUP BY t2.id ", $soutezId, $soutezId, $soutezId, $soutezId ); } Edit: ješte jsem přemýšlel nad korelovaným dotazem, ale to se mi zdá, že by bylo mnohem pomalejší ... Tj. místo LEFT JOIN ( SELECT SUM(vyhra) total, user_id FROM tip_users_tikety WHERE soutez_id = %i AND vyherni = 1 GROUP BY user_id ) tmp3 ON tmp3.user_id = t2.id něco jako (SELECT SUM(vyhra) total FROM tip_users_tikety WHERE soutez_id = %i AND user_id = t2.id AND vyherni = 1 ) as total |
||
Tori Profil |
Jen se chci zeptat (snažím se pochopit ten dotaz a tomuhle nerozumím): K čemu je tabulka tmp1 - omezení řádků v t2 pouze na tipující? Připadá mi totiž, že ve výsledku dělá totéž jako
JOIN tip_users_tikety t3 ON t3.user_id = t2.id WHERE t3.soutez_id = %i GROUP BY t2.id edit: #4: samozřejmě, doufám nezapomenu. :) |
||
Kajman Profil |
Pokud bude třeba 20000 uživatelů, ale např. díky limitu se bude vypisovat jen 20 (a nebude se řadit podle některého ze součtů) měl by být korelovaný poddotaz svižnější. Jinak bude asi rychlejší počítání všeho najednou.
A souhlasím s Tori, těch joinů tam nemusí být tolik. |
||
Kcko Profil |
#4 · Zasláno: 3. 1. 2013, 13:43:48 · Upravil/a: Kcko
Tori:
Nepleteš se Tori, je to tam duplicitně, když jsem ten dotaz skládal, tak jsem si toho všiml až na konci, ten JOIN je zbytečný v tom prvním dotazu stačí mít pouze Idčka uživatelů a až pak je spojit s tabulkou users kvůli jejich přezdívce :) jsi bystrá. Nicméně, tohle není hlavní dotaz, ale díky za zájem. PS. Můžeme si tykat ne? Kajman: Ok, díky za info. Jinak principiálně to spojení je v pořádku, nevím čím to je, možná únavou, ale pořád žiju v domnění, že jsem ten označený kus připojit špatně nebo zbytečně (myslím v těch LEFT JOINech), nějak jsem utvrzen v tom, že bych to tam měl spojit s Id uživatelem ... nebo je to takhle v pořádku? |
||
Tori Profil |
Kajman:
A pomohlo by seskupit první dvě tabulky? (= jestli by se pak tmp2 a tmp3 připojily jen k těm vybraným řádkům z t2. Nevím jestli to optimizér umí sám udělat i v tom původním dotazu, nebo se mu to musí říct.) FROM (users t2 JOIN tip_users_tikety t3 ON t3.user_id = t2.id AND t3.soutez_id = %i) LEFT JOIN ( ... ) tmp2 -- atd. |
||
Kcko Profil |
Nechme to být :). Mám tu ještě jeden oříšek.
SELECT r.prijmeni, r.jmeno, COUNT(zk.udalost) AS zlute, COUNT(ck.udalost) AS cervene, COUNT(r.id_rozhodci) AS pocet, r.id_rozhodci FROM utkani u JOIN rozhodci r ON r.id_rozhodci=u.id_rozhodci1 AND r.status='ok' LEFT JOIN karty zk ON u.id_utkani=zk.id_utkani AND zk.udalost='zk' LEFT JOIN karty ck ON u.id_utkani=ck.id_utkani AND ck.udalost='ck' WHERE u.sezona='2013' AND u.soutez='Zima' GROUP BY u.id_rozhodci1 ORDER BY pocet DESC, cervene DESC, zlute DESC Tento dotaz vyhodí seznam rozhodčích, počet odpískaných zápasů a počet rozdaných karet. Nicméně počet zápasů nikdy nesouhlasí, díky těm LEFT JOINům se vždy připočte +1 V DB: takto utkani ======== zapas zapas karty ======== zk zk rozhodci ======== rozhodci Mělo bý to vrátit ============ rozhodčí | 2 ZK | 0 CK | 2 utkani Vrací mi to pořád 3 utkání, než se pustím do totálního přepisování (dotazu nebo aplikace) nemá někdo tucha jak to inteligentně a nenáročně fixnout, mě to dneska nemyslí .. :| |
||
Kajman Profil |
Kcko:
„Nechme to být :)“ Pokud to je svižné, tak je nejjednodušší řešení nechat dotaz být. K druhému dotazu... count(distinct u.id_utkani) AS pocet |
||
Kcko Profil |
Kajman:
DISTINCT funguje. Tedy pouze tvůj navržený, pokud jej přidám i ke kartám ukazuje to špatný počet karet. (Místo 2 ZK, ukazuje 1 ZK). Nerozumím tomu ovšem ... můžu požádat o vysvětlení Edit: Přidal jsem 1 CK COUNT( DISTINCT zk.udalost) AS zlute, COUNT( DISTINCT ck.udalost) AS cervene, COUNT( DISTINCT u.id_utkani) AS pocet, A výsledek je 2 utkani, 1 ZK, 1 CK, což je špatně správně to je 2-2-1 Ještě nějaká idea? |
||
Kajman Profil |
#9 · Zasláno: 3. 1. 2013, 16:32:29
Ta poslední věta znamená, že máš použít distinct nad primárním klíčem tabulky karty.
|
||
Kcko Profil |
#10 · Zasláno: 3. 1. 2013, 19:10:40
Kajman:
Funguje díky. Já jsem si ten dotaz rozepsal, abych viděl co ty LEFT JOINy vytvoří a je to takto řádek - hodnoty řádek - hodnoty řádek - same NULL hodnoty (to v mém případě je ten / byl ten problém). Jak se tady tedy zachová ten count distinct, snažím se to pochopit, ale nedocvakne mi to. Každopádně díky. |
||
Kajman Profil |
#11 · Zasláno: 3. 1. 2013, 19:16:17
Ten řádek s null hodnotou nebyl problém, problémem pro sčítání byly ty dva řádky předtím, kdy se jednomu zápasu přiřadily dvě karty. A kdyby tam byly např. ještě tři červené karty, řádků s jedním zápasem by bylo 6.
Distinct v count počítá pouze jedinečné nenullové hodnoty. Viz. manuál. |
||
Kcko Profil |
#12 · Zasláno: 3. 1. 2013, 19:27:38
Tak jo bezva, děkuji.
|
||
Časová prodleva: 11 let
|
0