Autor Zpráva
VaKvas
Profil
Zdravim a prosim o pomoc. Potrebuji zrychlit(optimalizovat) nasledujici dotaz do db. Provadim generovani jine tabulky, kde v cyklu cca 5000 zaznamu vykonavam tento dotaz.

Takze v kazdem cyklu potrebuji sahnout do tabulky payments, kde si musim vysoucovat castku za obdobi (paysum) pak potrebuji zjistit pocet nalezenych zazanamu za dane obdobi. Proto ty SubSelecty. Ale urcite by to slo napsat lepe. Prosim o radu.

V rodicovskem cyklu ziskavam prave mrp_cislo a to datum. Rodic vrati prace cca 5000 zaznamu ja nasledne v cyklu prochazim zaznamy a dotahuji tato data. Snad je to srozumitelne .. :-)

SELECT p.name,p.amount,p.contractId,p.branchId, 
            
    (SELECT sum(amount) FROM payments p WHERE contractId = (SELECT id FROM contracts WHERE mrp_cislo ='20111485') 
     AND '2012-10-31' BETWEEN p.since AND IFNULL(p.to, '2099-12-31')) as paysum,   // soucet za dane obdobi

    (SELECT count(id) FROM payments p WHERE contractId = (SELECT id FROM contracts WHERE mrp_cislo ='20111485') 
     AND '2012-10-31' BETWEEN p.since AND IFNULL(p.to, '2099-12-31')) as rows      // potrebuji zjistit pocet nalezenych za dane obdobi

FROM payments p WHERE contractId = (SELECT id FROM contracts WHERE mrp_cislo ='20111485')
     AND '2012-10-31' BETWEEN p.since AND IFNULL(p.to, '2099-12-31')
Kajman
Profil
Ověřte si v explain, zda se používají vhodně indexy.
Poddotaz ve where raději přepište na inner join.
Ty dva poddotazy v select části zkuste spočítat jedním dotazem připojený přes join.
A zkuste místo 5000 dotazů udělat jeden s použitím group by.
VaKvas
Profil
Ty joiny celkem motam. Mohu poprosit o vzor, jak joiny spravne pouzit v tomto pripade..
Jednoduche JOINy davam, ale tady se v tom vzdycky zamotam..

Diky!
Majkl578
Profil
V MySQL doporučuji nepoužívat závislé poddotazy (dependent subquery), MySQL má problém s aplikováním indexů a čas vykonávání dotazů exponenciálně roste s počtem záznamů, na 5000 řádků může být i 1000x horší než udělat n+1 dotazů.
Byl by problém oddělit ty dva poddotazy do samostatných dotazů (a tedy provést 3 dotazy)? Napadá mě jedině konzistence výsledku, což by pro minulé (neměnné) období mělo být irelevantní.
Je mrp_cislo unikátní hodnota? Pokud ano, nedávají mi smysl ty poddotazy, pokud ne, nedávají smysl WHERE podmínky.
Nejlépe dodej zakládací script (create) tabulky.
VaKvas
Profil
Zkusim trochu popsat princip.
1. provadim import z CSV do tabulky MRP. /to tech cca 5000 zaznamu/
2. Prochazim tabulkou MRP a ziskavam contratctID /tedy mrp_cislo/ a datum zdan.pln., ktere mam pro ukazku vyplnene na pevno.
3. Na zaklade ziskanych dat z tabulky MRP prochazim platby/rozpady/ z tabulky payments
4. ukladam do dalsi tabulky....

Ukladani v bodu 4 delam pres multiinsert a probehne do par vterin (vsech cca 5000 radek)
mrp_cislo je uniq.

Zkousel jsem to dat do jednoho dotazu pridanim sum a cout, ale pak to musim nejak groupovat a uz neziskavam vsehcny zaznamy z tabulky payments... ale jen jeden zgrupovany.


Script na tabulku
A tady kod PHP (NETTE - ty to urcite znas ;))

Díky Majkle
Kajman
Profil
VaKvas:
a uz neziskavam vsehcny zaznamy z tabulky payments

Tak ke zgroupovaným datům pro výpočet součtů a počtů můžete připojit payments tabulku znovu. Něco jako

SELECT *
FROM   (SELECT m.id,
               m.varsym,
               m.ico,
               m.datzdanpln,
               m.firma,
               m.cislo_zak,
               m.sum,
               Sum(p.amount) AS paysum,
               Count(p.id)   AS rows,
               c.type,
               c.id          AS contractid
        FROM   mrp m
               LEFT JOIN contracts c
                      ON c.mrp_cislo = m.cislo_zak
               LEFT JOIN payments p
                      ON p.contractid = c.id
                         AND m.datzdanpln BETWEEN p.since AND Ifnull(p.to, '2099-12-31')
        WHERE  m.datzdanpln BETWEEN '2011-01-01' AND '2011-12-31'
        GROUP  BY m.id,
                  c.id) x
       LEFT JOIN payments p2
              ON p2.contractid = x.contractid
                 AND x.datzdanpln BETWEEN p2.since AND Ifnull(p2.to, '2099-12-31')

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: