mikrocontroller.net

Forum: PC-Programmierung SQLLite: Differenz zwischen zwei Datensätzen


Autor: Frank Esselbach (Firma: Q3) (qualidat)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In ener SQLLite-Datenbank wird immer dann ein neuer Datensatz 
eingetragen, wenn ein System seinen Zustand ändert, z.B. von Rüsten auf 
Fertigen oder von Fertigen auf Unterbrechen, von Unterbochen wieder auf 
Fertigen usw.

Wie ich aus den Datensätzen, nachdem ich sie per SQL-Select aus der 
Datenbank zurückgeholt habe, quasi "zu Fuß" die daraus resultierenden 
Differenzen und Summen berechne, ist nicht die Frage, das ist die 
"konventionelle" Lösung.

Die Frage ist, gäbe es ein SQL-Statement, dass es mir ermöglicht z.B. 
die Summe all der Zeiten zu ermitteln, die zwischen einem 
"Unterbrochen"-Status und dem darauffolgenden Zustand "Fertigen" liegen? 
Kann man mit SQL überhaupt Berechnungen zwischen den Datensätzen einer 
Ergebnismenge ausführen?

Frank

P.S. die Tabelle hat fogende ganz simple Struktur: Datum, Zeit, Status. 
Die möglichen Stati sind:

- Aus
- Rüsten (d.h. Einrichten für neuen Auftrag)
- Rüsten unterbrochen (z.B. Probleme mit dem Materialdurchlauf)
- Fertigen
- Fertigen unterbrochen (z.B. Werkzeug muss gewechselt werden)

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
grundsätzlich geht das schon, zumindest bei dem MS-SQL.

Ich würde da so ran gehen.

select
   sum( datediff(minute, s1.zeitpunkt,
          ( select min(zeitpunkt) from status s2 where s2.zeitpunkt > 
s1.Zeitpunkt and s2.status = "Rüsten unterbrochen")  ) )
from status s1
where
  s1.status = rüsten


aber wie man schon sieht ist das ganze nicht schön, also ist die 
Datenbankstruktur nicht für solche abfrage geeignet. Eventuell über ein 
trigger nachdenken der bei einem Status wechsel in eine extra tabelle 
dir Zeiten einträgt.

Autor: ... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf die Schnelle fallen mir da nur Subqueries ein.
Etwa so in der Art:
SELECT sum((SELECT t2.timestamp
              FROM logtable t2
              WHERE t2.timestamp > t1.timestamp
                AND t2.zustand = "Fertigen"
              ORDER BY t2.timestamp ASC
              LIMIT 1
            ) - t1.timestamp
          )
  FROM logtable t1
  WHERE t1.zustand = "Unterbrochen"

Dürfte allerdings fürchterlich ineffizient sein, insbesondere wenn die 
Tabelle etwas größer wird und die passenden Indizes fehlen. Eventuell 
ließe sich auch was mit einem JOIN machen, da will ich um die Uhrzeit 
aber nicht mehr drüber nachdenken :)

Eine andere Variante wäre es, die Summierung nicht erst im Nachhinein zu 
machen, sondern gleich wenn die entsprechenden Zustände auftreten. Also 
so etwa:
Zustand wechselt auf "Unterbrochen"
  --> Zeit merken
Zustand wechselt auf "Fertigen"
  --> gemerkte Zeit vorhanden?
      wenn ja -> Differenz bilden
                 summieren
                 gemerkte Zeit löschen

Du bräuchtest also noch ein oder zwei weitere Tabellen.

Autor: Frank Esselbach (Firma: Q3) (qualidat)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Variante mit dem Merken und gleich vollständig eintragen ist sicher 
in Bezug auf die Handhabbarkeit der Datensätze einfacher, hat aber 
andere Nachteile.

a) im Client müssen Zustände bzw. Werte "gemerkt" werden. Die gehen aber 
bei einem Absturz oder Stromausfall (kommt nicht häufig vor, aber bei 
hunderten von Clients eben doch immer mal wieder) verloren

b) um den zuvor angelegten Datensatz mit der Dauer zu vervollständigen, 
müssen Daten zurückgelesen bzw. geupdatet werden, was zusätzlichen 
Traffik verursacht ... Im Einzelfall auch kein Thema, aber durch die 
Multiplikation der vielen Clients schon ein Faktor

Erschwerend kommt hinzu, dass die Clients nicht direkt an der Datenbank 
hängen, sondern über einen sog. Multiplexer, der dann den Flaschenhals 
bildet.

Frank

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank Esselbach schrieb:
> um den zuvor angelegten Datensatz mit der Dauer zu vervollständigen,
> müssen Daten zurückgelesen bzw. geupdatet werden, was zusätzlichen
> Traffik verursacht
nur wenn man es nicht richtig macht. In datenbanken werden auch oft 
stored procedure verwendet. Den übergibst du einfach den Zeitpunkt und 
den aktuellen statuts und die Prozedure erledit das ganze datenbank zeug 
innerhalb der DB. Davon bekommt der client nichts mit.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nur damit du später keine Enttäuschung erlebst: SQLLite ist nicht gerade 
dafür gemacht "viele" Clients zu bedienen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.