Autor | Zpráva | ||
---|---|---|---|
vojak.p Profil |
#1 · Zasláno: 10. 9. 2013, 20:06:21
Zdravím, v databázi mam sloupeček datetime a value, standartně jsou tam uloženy vzorky po minutě(potřebuji zachovat vteřiny). Tyto hodnoty potom zobrazuji v grafu na PHP. Občas se ale někdy mezi vzorkama vytvoří hodinová mezera, jindy zase třeba vteřinová. Potřebuji tedy navrhnout funkci, aby nastavila čas, podívala se do DB, a přiřadila příslušnou hodnotu, v případě že tam nebude, přiřadí NULL. Inkrementuju minutu a opět se podívám do DB. Tím projedu všechny hodnoty. Chci takto vytáhnout hodnoty pro dnešní den - 2 dni zpět, to je 60*24*2=2880 až 60*24*3=4320 hodnot. Jak by bylo nejlepší to udělat?
|
||
Tori Profil |
4320 hodnot => min.4.5k pixelů, to bude pěkně velký graf...
Jinak asi šetrnější algoritmus by byl: nastavím do proměnné $čas začátek zobrazovaného období (jako timestamp) provedu SQL dotaz pro zjištění všech záznamů mladších než $čas načtu řádek dat z DB do $row dokud $čas < teď : pokud čas v $row === $čas : zobrazím hodnotu z $row načtu další řádek dat z DB do $row jinak : zobrazím NULL hodnotu $čas zvýším o 1 konec cyklu |
||
vojak.p Profil |
#3 · Zasláno: 10. 9. 2013, 20:51:31
Tori:
Ano, nějak takto bych to chtěl, ale jak udělat tu podmínku s časama? Mam porovnávat datum převedený na vteřiny? Jak udělám tu proměnou čas, chci něco ve stylu 2013-09-08 0:00:00 + 123 minutes = 2013-09-08 2:03:00? Jak mam porovnat čas 2:03:15 s 2:03:00 abych dostal shodu? |
||
Tori Profil |
1. datum si nastavíte např. pomocí strtotime (něco jako "now - 48 hours", projděte si manuál ohledně zápisu relativních časů), zformátujete pomocí
date('Y-m-d 00:00:00', $time) .
2. v SQL dotazu ten zformátovaný čas použijete úplně jednoduše ...WHERE sloupecDatetime > '$cas' , můžete si ho nechat vypsat rovnou jako timestamp (viz MySQL funkce UNIX_TIMESTAMP)
edit: Asi jsem nepochopila, s jakými časy jsou záznamy uložené. Jestli potřebujete použít něco jako "jakýkoli záznam vložený během této minuty", tak si datum ještě zaokrouhlete např. na celé minuty (pomocí DATE_FORMAT), až pak převeďte na timestamp. V PHP se musí také počítat s časy, které mají 0 vteřin: 02:02:00, 02:03:00, ... |
||
vojak.p Profil |
#5 · Zasláno: 10. 9. 2013, 21:22:19
Asi si nerozumíme. V DB mam čas uložený jako datetime. Potřebuji vytáhnout všechny hodnoty které jsou například v rozmení 1.9.2013 0:00:00 - 4.9.2013 0:00:00, pak je potřebuji jednotlivě zkontrolovat, v jedné minutě smí být jen jedna hodnota, další zahazuju. Chybí-li hodnota, doplním NULL. Poté výsledky zobrazím.
|
||
Taps Profil |
vojak.p:
tak zkus operátor between |
||
Tori Profil |
vojak.p:
„pak je potřebuji jednotlivě zkontrolovat, v jedné minutě smí být jen jedna hodnota, další zahazuju“ SELECT *, UNIX_TIMESTAMP(DATE_FORMAT(datum, '%Y-%m-%d %H:%i:00')) ts FROM tabulka WHERE datum BETWEEN '$od' AND '$do' GROUP BY ts |
||
vojak.p Profil |
#8 · Zasláno: 11. 9. 2013, 00:55:59
tak jsem to zatím navrhl takto:
vyčtu z databáze čas a k tomu proměnou za poslední 3 dny. Proženu to for cyklem, který kontroluje, zda rozdíl mezi $cas[$i] a $cas[$i+1] je větší jak 59. Tím vyloučím kratší intervaly. Poté zkontroluju jestli ten rozdíl je menší jak 120, omezím se na minutový interval, a zapíšu $value_new = $value. Je-li větší $value_new = NULL a k $cas[$i] přičtu 60 a znovu kontoluju. Tím vytvořím kompletní časovou osu po minutě. Celý script generování obrázku se zpozdí o 100ms, z 350 na 420ms, při 4320 hodnotách. |
||
PostCC Profil |
#9 · Zasláno: 11. 9. 2013, 06:57:34
vojak.p:
Zajímalo by mne, proč musí ta časová osa být kompletní? Za den to znamená 1440, za tři dny tedy skutečně 4320 hodnot. To je megagraf. Řešil jsem něco podobného a dospěl jsem k výsledku pomocí "časové osy", uzpůsobené šířce grafu. Hodnoty (výšky sloupců) pak mohou nabývat například maximálních, minimálních nebo průměrných hodnot v daném intervalu za předpokladu, že jeden sloupec neznamená jednu minutu, ale proměnný časový úsek. Do takto koncipovaného grafu lze pak nacpat libovolný časový interval s tím, že "rozsah" sloupce se automaticky uzpůsobí požadované šířce grafu. Dotaz pak vypadá nějak takto: SELECT FLOOR(TIME_TO_SEC(TIMEDIFF(T.Cas, '$Since')) / (TIME_TO_SEC(TIMEDIFF('$Until', '$Since')) / $GraphColumnCount)) AS TimeLine, T.Promenna AS Root, MAX(Hodnota) AS Pocet FROM THodnota AS T WHERE T.Cas BETWEEN '$Since' AND '$Until' GROUP BY FLOOR(TIME_TO_SEC(TIMEDIFF(T.Cas, '$Since')) / (TIME_TO_SEC(TIMEDIFF('$Until', '$Since')) / $GraphColumnCount)), Root ORDER BY TimeLine, Root Takto koncipovaný graf může pak obsahovat i více různých křivek (sloupců) pro různé veličiny, typicky teploty z více měřících stanic. Vstupem je časový inteval ($Since, $Until) a počet sloupců ($GraphColumnCount). Ve sloupci "TimeLine" je ve výsledku číslo sloupce v grafu, hodnoty nabývají rozsahu 0 - ($GraphColumnCount - 1). Výšky sloupců jsou obsaženy v "Pocet", agregační funkce určuje o jaké hodnoty půjde. Nabízím k úvaze pro použití, neznám pochopitelně přesné zadání, takže možná to stejně nevyhoví. |
||
Časová prodleva: 11 let
|
0