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


von Frank E. (Firma: Q3) (qualidat)


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)

von Peter (Gast)


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.

von ... (Gast)


Lesenswert?

Auf die Schnelle fallen mir da nur Subqueries ein.
Etwa so in der Art:
1
SELECT sum((SELECT t2.timestamp
2
              FROM logtable t2
3
              WHERE t2.timestamp > t1.timestamp
4
                AND t2.zustand = "Fertigen"
5
              ORDER BY t2.timestamp ASC
6
              LIMIT 1
7
            ) - t1.timestamp
8
          )
9
  FROM logtable t1
10
  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.

von Frank E. (Firma: Q3) (qualidat)


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

von Peter (Gast)


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.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.