Boardunity & Video Forum

Boardunity & Video Forum (https://boardunity.de/)
-   Programmierung und Datenbanken (https://boardunity.de/programmierung-datenbanken-f23.html)
-   -   MySQL, Einträge nach Tagen/Monaten gruppieren (https://boardunity.de/mysql-eintr-ge-tagen-monaten-gruppieren-t3735.html)

MrNase 14.11.2005 13:41

MySQL, Einträge nach Tagen/Monaten gruppieren
 
Also, ich habe ein kleines Wetterscript welches alle ~ 15 Minuten die aktuelle Temperatur meiner Heimatstadt in eine Datenbank einliest.

Nun möchte ich aber gerne ein Diagramm erstellen welches die Temperaturen im Jahresverlauf ausgibt und da stosse ich auf ein Problem:

Für jeden Tag habe ich rund (!) 96 Datensätze, alle tragen nen timestamp (via time();) und sind also auf die Sekunde genau zu bestimmen allerdings finde ich keinen Ansatz wie ich den Tagesdurchschnitt berechnen kann also wie ich alle Eintrage des Tags X gruppieren kann damit ich die entsprechenden Werte für ein Diagramm habe.

Eigentlich müsste die Abfrage folgendes leisten:

Tag 1: alle Tageswerte addiert = X
X / Anzahl der Tageswerte von Tag 1 = Tagesdurchschnitt von Tag 1

Tag 2:
alle Tageswerte addiert = X
X / Anzahl der Tageswerte von Tag 2 = Tagesdurchschnitt von Tag 2



Datenbankstruktur schaut wie folgt aus:

id -> auto_increment
zeit -> int(11)
temperatur -> int(10)


So sollte das Diagramm später mal aussehen:

Code:


 ^
 |
 |
 |      2
 |      _  3
 |  1  | |  _
 |  _  | | | |
_|_|_|_|_|_|_|___>
 |



codethief 15.11.2005 19:44

Hol dir alle Datensätze aus der Datenbank und finde mit getdate() oder date() das Datum von jedem Datensatz heraus. Dann musst du alle Datensätze eines Tages in ein Array (ein Objekt wäre evtl. noch klüger) tun und kannst die Daten auswerten. Ausgewertete Daten von bereits vergangenen Tagen würde ich der Performance wegen in einer anderen MySQL Tabelle abspeichern. Ob du nun alte Temperaturwerte löschst, bleibt dir überlassen. Die Statistik ginge dadurch ja nicht verloren.

Ich hab dir mal den eine komplette Klassenlib dazu geschrieben. Mit DayTempAnalyser::getAverages() bekommst du alle Tage, sowohl vergangene als auch den aktuellen, in einem Array. Die Datenbankfunktionen musst du natürlich ggf. durch eine andere Datenbankschnittstelle (DBKlasse oder so) ersetzen.
DayTempAnalyser ist eine Schnittstelle zu deiner Statistik, Day repräsentiert einen noch nicht vollendeten oder noch nicht vollständig ausgewerteten Tag (mit einer vorläufigen Tagesdurchschnittstemperatur), DayAverage hingegen einen schon vergangenen Tag mit einem abgeschlossenen bzw. endgültigen Durchschnitt.

PHP-Code:

class DayTempAnalyser
{
    private static 
$dayaverages = array();
    
    
    public static function 
getAnalysedDays()
    {
        
$get_averages mysql_query("SELECT * FROM dayaverages ORDER BY `date`");
        
        
$analysed_days = array();
        
        while(
$day mysql_fetch_array($get_averages))
        {
            
$analysed_days[$day['date']] = new DayAverage($day['date']);
            
            
$analysed_days[$day['date']]->setAverage($day['average']);
        }
        
        return 
$analysed_days;
    }
    
    public static function 
analyseNewTemperatures()
    {
        
$get_temps mysql_query("SELECT * FROM temperatures");
        
        while(
$temp mysql_fetch_array($get_temps))
        {
            
$date date("d-m-Y"$temp['timestamp']);
            
            if(!isset(
$this->dayaverages[$date])
            {
                
$this->dayaverages[$date] = new Day($date);
            }
            
            
$this->dayaverages[$date]->addTemperature($temp['temperature']);
        }
        
        foreach(
$this->dayaverages as $day)
         {
             
$day->calculateAverage();
             
$day->save();
         }
    }
    
    
    public static function 
getAverages()
    {
        
self::analyseNewTemperatures();
        
        return 
array_merge($this->dayaveragesself::getAnalysedDays());
    }
    
    
    
    
    public static function 
deleteDay($date)
    {
        unset(
$this->dayaverages[$date]);
    }
}




class 
Day
{
    private 
$date "";
    private 
$temperatures = array();
    private 
$average 0;
    
    public function 
__construct($date)
    {
        
$this->date $date;
    }
    
    public function 
addTemperature($temp)
    {
        
$this->temperatures[] = $temp;
    }
    
    public function 
calculateAverage()
    {
        
$sum 0;
        
        foreach(
$this->temperatures as $temperature)
        {
            
$sum += $temperature;
        }
        
        
$this->average $sum count($this->temperatures);
    }
    
    public function 
getAverage()
    {
        return 
$this->average;
    }
    
    public function 
save()
    {
if(
$this->date == date("d-m-Y")) // Durchschnitte vom aktuellen Tag können sich noch ändern, deshalb noch nicht speichern.
        
{
            return 
false;
        }
        else
        {
            
mysql_query("INSERT INTO dayaverages (`date`, average) VALUES ('".$this->date."', '".$this->average."')");
            
            
$date_exp explode("-"$this->date);
            
$day_start mktime(000, (int) $date_exp[1], (int) $date_exp[0], $date_exp[2]);
            
$day_end mktime(245959, (int) $date_exp[1], (int) $date_exp[0], $date_exp[2]);
            
            
// ausgewertete Temperaturen löschen
            
mysql_query("DELETE FROM temperatures WHERE `timestamp` >= ".$day_start." AND `timestamp` <= ".$day_end);
            
            
DayTempAnalyser::deleteDay($this->date);
        }
    }
}


class 
DayAverage extends Day
{
    private function 
addTemperature($temp) { }
    private function 
calculateAverage() { }
    private function 
save() { }
    
    public function 
setAverage($average)
    {
        
$this->average $average;
    }


Du könntest natürlich auch noch entsprechende Methoden bauen, um neue Temperaturen in die Datenbank einzufügen und evtl. sogar eine Methode, die dir basierend auf dem Array von DayTempAnalyser::getAverages(), ein fertiges Diagramm baut. Du könntest sogar soweit gehen und den Durchschnitt eines Monats oder eines ganzen Jahrs mit der Lib berechnen oder Höchst- und eine Niedrigsttemperaturen einbauen.

Die Datenbank für die Lib müsste folgendermaßen aussehen:

temperatures
- timestamp INT
- temperature FLOAT

dayaverages
- date VARCHAR(10) - im Format d-m-Y (kannst natürlich auch einen anderen Datentyp nehmen, du musst nur den Code entsprechend anpassen - VARCHAR war für mich jetzt am leichtesten, weil ich mit dem DATE Datentyp nur wenig Erfahrung habe)
- average FLOAT

Du kannst natürlich noch weitere Felder hinzufügen, wie du lustig bist. :)

Und achja - ich hab die Lib nicht getestet, also es könnten noch Bugs drin sein. ;)


codethief.

TRS 16.11.2005 09:26

Theorie: Die Funktion FROM_UNIXTIME(unix_timestamp,format) in Kombination mit groupby sollten dies ermöglichen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:26 Uhr.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25