Autor | Zpráva | ||
---|---|---|---|
BunnyBugs Profil * |
#1 · Zasláno: 21. 4. 2016, 13:23:51
Zdravím, mám po dlouhé době zase dotaz.
V DB mám uloženy různé akce se sloupcem datum start a datum konec. A já bych teď potřeboval vypsat celé datum všech dnů, jak toho prosím docílím? Příklad: V DB akce 1 datum start = 10.3.2015, datum konec = 14.3.2015 V DB akce 2 datum start = 18.4.2015, datum konec = 22.4.2015, atd... A výsledek by měl být: 10.3.2015 11.3.2015 12.3.2015 13.3.2015 14.3.2015 18.4.2015 19.4.2015 20.4.2015 21.4.2015 22.4.2015 Děkuji moc za rady. |
||
Kajman Profil |
#2 · Zasláno: 21. 4. 2016, 14:27:17
Pokud to má vypsat už databáze, tak např. pomocnou kalendářovou tabulkou, kde budou nachystány všechny dny (začátek a konec si stanovte dle potřeb). Pak stačí obyčejný join na tuto tabulku
... akce a join kalendar k on k.datum between a.start and a.konec Tabulka může mít i pomocné sloupce rok, měsíc, den v týdnu, příznak svátku, které se mohou hodit při jiných dotazech. Pokud to má vypsat až php, tak budete přičítat postupně jeden den až do limitu, tam komplikace nejsou. |
||
BunnyBugs Profil * |
#3 · Zasláno: 21. 4. 2016, 14:56:38
Kajman:
Tak vlastně ani nevím, co je lepší, jestli to vypsat už databází, či až potom php. V podstatě potřebuji jen do hotového kalendáře zvýraznit datumy, kdy se něco dělo. Umím zvýraznit start i konec akce, ale pokud je to třeba čtyřdenní akce, tak ty dny mezi startem a koncem se mi prostě nedaří, proto bych potřeboval nějakou konkrétní radu. |
||
juriad Profil |
Asi bych na to šel takto:
SELECT start AS datum, 'start' AS typ FROM tabulka WHERE konec >= '2016-04-01' AND start < '2016-05-01' UNION ALL SELECT konec AS datum, 'konec' AS typ FROM tabulka WHERE konec >= '2016-04-01' AND start < '2016-05-01' ORDER BY datum ASC, type DESC Toto vrátí všechny události, které protínají duben. Událost je dvou typů: start, konec. V PHP pak bude zpracování vypadat: $zaznam = mysqli_fetch_assoc(...); # načteme první záznam $in_progress = 0; # počet právě probíhajících událostí foreach (duben as $den) { # procházíme dny v dubnu # zpracujeme všechny staré záznamy a ještě aktuální začátky while ($zaznam && ($zaznam['datum'] < $den || $zaznam['datum'] == $den && $zaznam['typ'] == 'start')) { $in_progress += $zaznam['typ'] == 'start' ? 1 : -1; # podle typu upravíme počet probíhajících událostí $zaznam = mysqli_fetch_assoc(...); # načteme další záznam } # využijeme informaci o počtu událostí: if ($in_progress > 1) { echo "<b title=\"$in_progress událostí\">$den</b>"; } else { echo "$den"; } } Ta agregace, která se provádí ve smyčce while by šla provést i v databázi. To by bylo vhodné, pokud by existovaly více než desítky událostí za měsíc. |
||
BunnyBugs Profil * |
#5 · Zasláno: 21. 4. 2016, 16:06:10
juriad:
Tak z tohohle jsem úplně mimo :( Navíc používám MySQL. |
||
juriad Profil |
Ten dotaz je pro MySQL.
Pro události (škrtnuté jsou mimo duben; pro přehlednost seřazené podle začátku, to však není nutné): 2016-03-20 až 2016-04-04 2016-04-01 až 2016-04-06 2016-04-02 až 2016-04-04 2016-04-06 až 2016-04-07 2016-04-12 až 2016-04-18 2016-04-15 až 2016-04-18 2016-04-20 až 2016-04-20 2016-04-29 až 2016-05-03 vrátí dotaz záznamy v tomto pořadí: 2016-03-20, start 2016-04-01, start 2016-04-02, start 2016-04-04, konec 2016-04-04, konec 2016-04-06, start 2016-04-06, konec 2016-04-07, konec 2016-04-12, start 2016-04-15, start 2016-04-18, konec 2016-04-18, konec 2016-04-20, start 2016-04-20, konec 2016-04-29, start 2016-05-03, konec Co se bude dít v jednotlivé dny: 1. dubna se zpracují první dva záznamy (zpracováním myslím 6. řádku mého skriptu), víme, že 2 události jsou aktivní 2. dubna se zpracuje další záznam => 3 aktivní 3. duben není zajímavý 4. dubna se nezpracuje nic, protože typ události je konec, žádný začátek 5. dubna se zpracují staré události (konec 4. dubna) => 1 aktivní 6. zpracován začátek 6. dubna => 2 aktivní 7. zpracován konec 6. dubna => 1 aktivní 8. zpracován konec 7. dubna=> 0 aktivních 9. až 11. je stále 0 aktivních 12. => 1 aktivní 13., 14. nic se neděje, stále 1 aktivní 15. => 2 aktivní 16., 17. nic se neděje, stále 2 aktivní 18. se nic neděje, konec se zpracuje následující den 19. => 0 aktivních 20. => 1 aktivní 21. zpracován konec 20. dubna => 0 aktivních 22. - 28. stále 0 aktivních 29. dubna => 1 aktivní 30. dubna, stále 1 aktivní konec dubna, zbytek dat zahodíme Výsledkem je (den, počet událostí): 1, 2 2, 3 3, 3 4, 3 5, 1 6, 2 7, 1 8, 0 9, 0 10, 0 11, 0 12, 1 13, 1 14, 1 15, 2 16, 2 17, 2 18, 2 19, 0 20, 1 21, 0 22, 0 23, 0 24, 0 25, 0 26, 0 27, 0 28, 0 29, 1 30, 1 |
||
BunnyBugs Profil * |
#7 · Zasláno: 21. 4. 2016, 17:28:13
juriad:
jojo, díky za vysvětlení, co se stane, to bych celkem chápal, ale úpravách k mé DB mi to vypisuje tyto chyby: Notice: Use of undefined constant duben - assumed 'duben' in C:\xampp\htdocs\... on line 12 Warning: Invalid argument supplied for foreach() in C:\xampp\htdocs\... on line 12 V řádku 12 mám toto: foreach (duben as $den) { # procházíme dny v dubnu |
||
juriad Profil |
#8 · Zasláno: 21. 4. 2016, 17:55:53
BunnyBugs:
Nesmíš mi tak slepě věřit. Ty zvýrazněné části kódu tam nejsou na okrasu. Myslel sis, že ti dám kód, který ti bude fungovat okamžitě, když o tvojem skriptu nevím vůbec nic? Ten cyklus si musíš naprogramovat sám, stejně tak i ta porovnání datumů. Datumy můžeš v PHP reprezentovat různě, třeba jako string nebo jako objekt DateTime. Například takto: ... $d = new DateTime('first day of 2016-4'); # ten rok a měsíc si od někud musíš dosadit, stejně jako do toho SQL dotazu $interval = new DateInterval('P1D'); $last = new DateTime('last day of 2016-4'); do { # místo foreach použiješ do-while $den = $d->format('Y-m-d'); ... } while($d->add($interval) <= $last); |
||
BunnyBugs Profil * |
#9 · Zasláno: 21. 4. 2016, 19:32:19
Tak nevím, jestli je to úplně správně, ale vyřešil jsem to takto a funguje to:
$DBAkce = mysql_query("SELECT `datumstart`, `datumkonec` FROM `jizdy` WHERE `stavjizdy` = 'ANO'"); while ($ColAkce = mysql_fetch_array($DBAkce)){ $Start = new Datetime($ColAkce['datumstart']); $Konec = new Datetime($ColAkce['datumkonec']); $PomerDatum = $Start -> diff($Konec); $PocetDni = ($PomerDatum -> format("%d")); $events [date("Y-m-d", strtotime($ColAkce['datumstart']))] = $ColAkce['datumstart']; $this_day = strtotime($ColAkce['datumstart']); for ($i = 0; $i <= $PocetDni; $i++){ $events [date("Y-m-d", $this_day = strtotime("+1 day", $this_day))] = $ColAkce['datumstart']; } } |
||
Časová prodleva: 9 let
|
0