Autor Zpráva
Ulet
Profil *
Zdrávím mohl by mi někdo poradit s řazením při výpisu z databáze? SQL dotaz je docela zdlouhavý tak ho sem nebudu dávat celý můj problém je tento:
Mám tabulku "hodnoty" kde se ukládá datum, co potřebuji udělat je zjistit kolik pracovních dnů je mezi tímto datem a dneškem
nyní to řeším tak že si udělám
DATEDIFF(DATE_FORMAT(datum, '%Y-%m-%d'), CURDATE()) AS rozdil
a podle toho to řadím.
No a abych dosáhl toho že v potřebných případech vypíšu jen pracovní dny tak jsem si vytvořil tabulku kalendáře kde jsou sobota, neděle a svátky označeny a dotazem
SELECT COUNT(*) as count FROM calendar WHERE svatek=0 AND pracovni_den=1 AND datum BETWEEN '$od' AND '$do'
zjistím dannou hodnotu kterou pak vypíšu, no nicméně jsou ve výpisu i hodnoty u kterých se svátky/so/ne počítají tudíž vypisuji přímo výsledek prvního dotazu, a v těchto případech mi pak nesedí řazení (někdy se prostě po odečtu svátků číslo změnší ale protože se to řadí podle hodnoty bez odečtu tak se zařadí špatně)
Jediná možnost co mě napadla vytáhnout si to z databáze tak jak to dělám nyní a řadit až výsledné pole ale raději bych to měl dotazem ;-)
Tori
Profil
Čistě ze zvědavosti - opravdu je potřeba sloupce svatek i pracovni_den, nestačil by jeden? (= existují pracovní svátky?)
Pokud sloupeček datum je typu DATETIME (tipuju), mělo by místo DATE_FORMAT jít použít i jen DATE(datum).
------
Jinak funguje mi (= správně počítá počet dní a tedy i podle něj řadí) takovéhle řešení:
Tabulka udalosti:
ID (INT, auto increment, PK)
datum (DATE)
pocitatSvatky (BOOLEAN)  -- pokud 1, budou se od data události do dneška počítat i svátky

Tabulka kalendar
datum (DATE, PK)
jeSvatek (BOOLEAN)  -- 1, pokud je svátek
index přes sloupce DATE + jeSvatek
SQL:
SELECT u.*, COUNT( * ) 
FROM `udalosti` u
JOIN kalendar k ON k.datum >= u.datum
AND k.datum < '2012-11-24'
AND k.jeSvatek <= u.pocitatSvatky
GROUP BY u.id
Tori
Profil
Oprava - předchozí dotaz počítal pouze s událostmi v minulosti a byl pomalý (2s). Tohle je trochu rychlejší (0.65s) varianta. Pokusná data: tabulka udalosti má 350 řádků, v budoucnosti jen asi 6 z nich; tabulka kalendar má cca 2400 řádků mezi 1990 a 12/2012.
V tabulce kalendar jsou teď jenom datumy svátků:
Tabulka udalosti:
ID (INT, auto increment, PK)
datum (DATE)
pocitatSvatky (BOOLEAN)  -- pokud 1, budou se od data události do dneška počítat i svátky
index "udatum" přes sloupce 'datum' a 'pocitatSvatky'

Tabulka kalendar
datum (DATE, PK?)
jeSvatek (BOOLEAN)  -- má vždy hodnotu 1
index "kdatum" přes sloupce 'datum' a 'jeSvatek'

SQL: V jednotlivých dotazech můžete v části LIMIT použít jakékoli velmi vysoké číslo. Bez LIMIT by se totiž ignorovala část "ORDER BY NULL", která je potřeba, aby se zbytečně neřadila data třikrát. Místo CURDATE() je lepší si v PHP složit aktuální datum ve správném formátu a použít ho jako řetězec, MySQL si tak může výsledek dotazu cachovat.
Pokud by některý dotaz - např.události v minulosti - vracel většinu řádků z tabulky událostí, tak se nemusí použít index "udatum". Zakomentovanou částí si můžete jeho použití vynutit, ale je v tom jen malý rozdíl, cca 0.64-0.65s oproti 0.65-0.57s bez indexu.
(SELECT u.*, DATEDIFF(u.datum, '2012-11-25') + COUNT(k.datum) 'rozdil'
FROM `udalosti` u -- FORCE INDEX(udatum)
LEFT JOIN kalendar k ON k.datum >= u.datum AND k.datum < '2012-11-25' AND u.pocitatSvatky = k.jeSvatek
WHERE u.datum < '2012-11-25'
GROUP BY u.id ORDER BY NULL LIMIT 1, 123456789
)
UNION ALL 
(SELECT u.*, 0 AS 'rozdil'
FROM udalosti u
WHERE datum = '2012-11-25'
)
UNION ALL
(SELECT u.*, DATEDIFF(u.datum, '2012-11-25') - COUNT(k.datum) 'rozdil'
FROM `udalosti` u
LEFT JOIN kalendar k ON k.datum > '2012-11-25' AND k.datum <= u.datum AND u.pocitatSvatky = k.jeSvatek
WHERE u.datum > '2012-11-25'
GROUP BY u.id ORDER BY NULL LIMIT 1, 123456789
)
ORDER BY rozdil DESC
Ulet
Profil *
Čistě ze zvědavosti - opravdu je potřeba sloupce svatek i pracovni_den, nestačil by jeden? (= existují pracovní svátky?)
Máte pravdu, stačilo by, mezi svátkem a so/ne ve výsledku není rozdíl.

Pokud sloupeček datum je typu DATETIME (tipuju), mělo by místo DATE_FORMAT jít použít i jen DATE(datum).
I v tomto případě máte pravdu ;-)

Bohužel jsem se až nyní dostal k PC a ještě né k tomu svému, večer vyzkouším Vaše řešení a dám vědět.

Děkuji i za tipy CURDATE() jsem do dnes vesele využíval s vědomím že to dělám správně... no koukámk že to nebyla tak úplně pravda ;-)
Ulet
Profil *
Super podařilo se rozchodit nápad uložit si do tabulky jestli se svátekm mám počítat nebo ne bylo asi to co jsem neudělal :-)

Díky MOC!! :-)
Kajman
Profil
Proč to neřadit jen podle datumu? Starší datum přeci nemůže mít do dneška méně pracovních dní než mladší datum.
Tori
Profil
Kajman:
On právě u některých událostí chce počítat i svátky, zatímco u jiných ne. Nicméně, šlo by tu moji variantu nějak zjednodušit (případně úplně jinak to udělat)? Pořád mi to na to celkem malé množství dat připadá dost pomalé.
Kajman
Profil
Tori:
On právě u některých událostí chce počítat i svátky, zatímco u jiných ne.

Aha, nevšiml jsem si.

šlo by tu moji variantu nějak zjednodušit?

Co si v kalendáři předpočítat pořadové číslo pracovního dne a svátku nebo tak něco? Pak není potřeba group by s count(), jen se připojí jediný řádek a jen se odečtou dvě čísla.

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:

0