Cytat(trueblue @ 5.03.2018, 08:09:38 )

Rozwiązanie mmmmmmm nie jest prawidłowe, bo opiera się na założeniu, że rekordy są w postaci ciągłej. Wystarczy zmienić 13:42 kończącą zakres zer na 13:50 i dalej kolejne godziny, i wynik jest niepoprawny. Pisałem, że rozwiązanie, które podałem można uprościć gdyby rekordy były w postaci ciągłej, ale w Twoim założeniu może być przerwa.
Masz rację, nie pomyślałem o tym, przy sprawdzaniu.
Cytat(trueblue @ 5.03.2018, 08:09:38 )

Zamiast zapytania, możesz wynik "otrzymywać" w trakcie zapisu rekordów. Mianowicie tworzysz drugą tabelę z godziną, flagą i ilością, i w momencie pojawienia się nowego rekordu:
1. Jeśli dla danej godziny jest flaga 0 i ostatnia zapisana godzina miała również flagę 0, to dodajesz do kolumny ilość ostatniego rekordu 1.
2. Jeśli dla danej godziny jest flaga 0 i ostatnia zapisana godzina miała flagę 1, to zapisujesz nową godzinę z ilością 0 i flagą 0.
3. Analogicznie robisz dla flagi 1.
Że też na to nie wpadłem, to jest chyba najsensowniejsze. Zaraz coś napiszę o zobaczę, ale chyba to jest to.
Wydaje mi się, że ogarnąłem.
Zrobiłem tak.
1. Plik tworzony, dla każdego testowanego hosta
"<?php
require '" . $_SERVER['DOCUMENT_ROOT'] . "/class/db_login.php';
require '" . $_SERVER['DOCUMENT_ROOT'] . "/class/Sql.class.php';
require '" . $_SERVER['DOCUMENT_ROOT'] . "/class/Dvr.class.php';
\$sql = new Sql( \$db_host, \$db_user, \$db_passwd, \$db_name );
\$dvr = new Dvr( \$sql, null, null);
\
$sock = @fsockopen( '" . long2ip($data['dvr_wan_ip_address
']) ."', '" . $data['dvr_wan_tcp_port
'] . "', \
$num, \
$error, 1
); if( !\$sock ) { \$status = '0'; }
if( \
$sock ) { \
$status = '1'; fclose(\
$sock); } if (\$dvr->get_last_dvr_status_count_id('" . $dvr_mac_address . "') == null) {
\$dvr->add_new_event_to_dvr_status_count('" . $dvr_mac_address . "', \$status);
\$dvr->add_new_event_to_dvr_status('" . $dvr_mac_address . "', \$status);
}
else {
if ( \$dvr->get_last_dvr_status('" . $dvr_mac_address . "') == \$status ) {
\$dvr->add_count_to_dvr_status_count(\$dvr->get_last_dvr_status_count_id('" . $dvr_mac_address . "'));
\$dvr->add_new_event_to_dvr_status('" . $dvr_mac_address . "', \$status);
}
if ( \$dvr->get_last_dvr_status('" . $dvr_mac_address . "') != \$status ) {
\$dvr->add_new_event_to_dvr_status_count('" . $dvr_mac_address . "', \$status);
\$dvr->add_new_event_to_dvr_status('" . $dvr_mac_address . "', \$status);
}
}
?>";
Objaśnienie:
Pobieramy z głównej tabeli ostatni status
public function get_last_dvr_status($dvr_mac_address) {
$result = $this->sql->query("
SELECT dvr_test_status
FROM dvr_status
WHERE dvr_status_id=(
SELECT MAX(dvr_status_id)
FROM dvr_status
WHERE dvr_status_dvr_mac_address = '$dvr_mac_address'
)
LIMIT 1
");
if($result === false) {
$info = "Wystąpił błąd z bazą danych. Błąd: " . $this->sql->error;
return $info;
}
if($result->num_rows === 1) {
return $result->fetch_array()[0];
}
}
Pobieramy z tabeli pomocniczej ostatnie ID dla testowanego hosta
public function get_last_dvr_status_count_id($dvr_mac_address) {
$result = $this->sql->query("
SELECT dvr_status_id
FROM dvr_status_count
WHERE dvr_status_id=(
SELECT MAX(dvr_status_id)
FROM dvr_status_count
WHERE dvr_status_dvr_mac_address = '$dvr_mac_address'
)
LIMIT 1
");
if($result === false) {
$info = "Wystąpił błąd z bazą danych. Błąd: " . $this->sql->error;
return $info;
}
if($result->num_rows === 0) {
return null;
}
if($result->num_rows === 1) {
return $result->fetch_array()[0];
}
}
Zwiększamy licznik
public function add_count_to_dvr_status_count($last_dvr_status_count_id) {
$result = $this->sql->query("
UPDATE dvr_status_count
SET dvr_status_test_count = dvr_status_test_count + 1
WHERE dvr_status_id = '$last_dvr_status_count_id'
");
}
Jeśli w tabeli pomocniczej nie istnieje żaden wpis dla testowanego hosta, albo status jest inny
public function add_new_event_to_dvr_status_count($dvr_mac_address, $status) {
$status_info = ($status == '0') ? "OffLine" : 'OnLine';
$result = $this->sql->query("
INSERT INTO dvr_status_count (
dvr_status_id,
dvr_status_timestamp,
dvr_status_dvr_mac_address,
dvr_status_test_count,
dvr_status_info
)
VALUES (
NULL,
'" . date_create()->format('Y-m-d H:i') . "',
'$dvr_mac_address',
1,
'$status_info'
)");
}
I na koniec tak jak było do tabeli głównej dopisujemy zdarzenie (1/0)
public function add_new_event_to_dvr_status($dvr_mac_address, $status) {
$result = $this->sql->query("
INSERT INTO dvr_status (
dvr_status_id,
dvr_status_timestamp,
dvr_status_dvr_mac_address,
dvr_test_status
)
VALUES (
NULL,
'" . date_create()->format('Y-m-d H:i') . "',
'$dvr_mac_address',
'$status'
)");
}
Wszystko działa poprawnie, ale taka konkluzja mnie naszła, że w sumie mógłbym to zrobić na jednej tabeli.
W tabeli pomocniczej dodać tylko kolumnę ostatni status i zamiast pobierać go z głównej wszystko robić w tej pomocniczej.
Bo ta główna jest mi potrzebna do zliczenia ile razy był offline w ciągu np ostatnich 24h, ale przecież mogę sumować licznik, choć będzie to mniej dokładne,
bo jeśli licznik zaczął się 25h tamu i jest cały czas OffLine to mi nie zliczy poprawnie - jeśli się nie mylę.
Narobiłem się z tym, więc chyba zostawię tak jak jest - przynajmniej na razie. Mam jeszcze sporo innych rzeczy do ogarnięcia, więc niech działa jak działa.
Dzięki wszystkim za pomoc, temat rozwiązany - można zamknąć.