Autor Zpráva
BunnyBugs
Profil *
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
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 *
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 *
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-21 až 2016-03-25
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
2016-05-06 až 2016-05-08

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 *
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
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 *
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'];
            }
        }

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