Ausgabe eines Query anders als erwartet

Fuxxy1979

Benutzer
Beiträge
10
Hallo,

bin neu hier und habe nicht viel Erfahrung mit MySQL.

Ich möchte für die Arbeit ein kleines Kontrollprogramm schreiben, welches mir die Arbeit und die Übersicht ungemein erleichtern könnte. Bisher habe ich alles in eine Excel-Tabelle geschrieben.

Es geht hier um die Schichtzeiten und die Ruhepausen unserer LKW-Flotte.

Ich habe also in einer Tabelle, die LKW-Kennzeichen mit einer ID eingetragen und in einer zweiten Tabelle die Schichtzeiten, mit ID, LKW_ID, Beginn und Ende.

Die Ausgabe der Schichtzeiten war noch einfach. Mit der Ausgabe der Ruhepausen haperts ein wenig, da ich die Ende-Zeit aus der jeweiligen Zeile (passend zur LKW_ID) davor auslesen muss.

Ich habe einen Query gefunden und ihn für mich angepasst.

SELECT s1.lkw_id, s1.beginn, s1.ende, TIMEDIFF(s2.beginn, s1.ende)
FROM schichten s1
JOIN schichten s2
ON ( s2.schicht_id = (
SELECT MIN(schicht_id)
FROM schichten si
WHERE si.schicht_id > s1.schicht_id )
);


Das funktioniert auch soweit, solange nur eine LKW_ID in der Tabelle Schichten vorhanden ist. Sobald ein zweiter LKW eingetragen wird, sind einige Werte nicht mehr so passend.

Es hat sicherlich damit zu tun, dass ich ja die Ende-Zeit passend zur richtigen LKW_ID aus der vorherigen Zeile auslesen muss, nur bekomme ich das in den Query nicht eingefügt.

Ich bin für jede Hilfe dankbar.
 
Werbung:
Du wirst die LKW_ID mit in die Join-Condition einbauen müssen. Einfacher ginge das alles allerdings mit Window-Funktionen, die MySQL nicht kann. Oder anders formuliert: du hast die falsche DB gewählt.
 
Ich wollte es über eine Weboberfläche machen, davon habe ich bissel Ahnung. Die LKW_ID mit in die Join-Condition? Ich habe ehrlich gesagt keine Ahnung, wie ich das anstelle.

Was meinst du mit Windows-Funktionen, wie kann ich mir denn da was bauen, was mir eine Eingabe-Maske und eine Ausgabe-Oberfläche ausgibt?
 
Eingabemasken etc. sind hier nicht das Thema. Window-Funktionen (ohne s) sind spezielle Abfragetechniken, mit denen Du u.a. quasi ein gleitendes Fenster über eine Tabelle legen kannst (daher der Name) oder auch auf den n-ten Record vorher/nachher vom aktuellen zugreifen kannst etc. Sehr mächtiges Zeugs, kann aber mittlerweile eigentlich jede DB - mit Ausnahme von MySQL.
 
Ok, dann falsch verstanden oder falsch gelesen. Davon habe ich bisher noch nichts mitbekommen, scheint aber sehr interessant zu sein. Ist aber noch nichts für mich.

Vielleicht noch ein Tip, was den Join und die LKW-ID angeht?
 
Hey,
die Strukturen beider Tabellen helfen hier sicher ein wenig, um evtl mehr Lösungsansätze zu bekommen.

Ich glaube ich verstehe was du vorhast aber müsste das visualisiert haben.

Grüße
 
Was meinst du mit visualisiert? soll ich dir die Tabellenstruktur von beiden Tabellen zeigen?

CREATE TABLE `lkw` (
`lkw_id` int(11) NOT NULL,
`lkw_kennzeichen` varchar(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



CREATE TABLE `schichten` (
`schicht_id` int(11) NOT NULL,
`lkw_id` int(11) NOT NULL,
`beginn` datetime NOT NULL,
`ende` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


Die beiden lkw_id sind miteinander verknüpft.
 
Die beiden lkw_id sind miteinander verknüpft.

Davon ist nix zu seihen, kein Foreign Key.

Code:
test=# create table lkw(id int primary key, kennzeichen text);
CREATE TABLE
test=# create table schichten(id int primary key, lkw int references lkw, von_bis tsrange);
CREATE TABLE
test=# insert into lkw values (1, 'lkw1');
INSERT 0 1
test=# insert into lkw values (2, 'lkw2');
INSERT 0 1
test=# insert into schichten values (1, 1, '[2017-06-21 08:00:00,2017-06-21 13:00:00)');
INSERT 0 1
test=# insert into schichten values (2, 2, '[2017-06-21 08:00:00,2017-06-21 13:00:00)');
INSERT 0 1
test=# insert into schichten values (3, 1, '[2017-06-21 14:00:00,2017-06-21 16:00:00)');
INSERT 0 1
test=# insert into schichten values (4, 2, '[2017-06-21 15:00:00,2017-06-21 18:00:00)');
INSERT 0 1
test=# select * from schichten ;
 id | lkw |  von_bis   
----+-----+-----------------------------------------------
  1 |  1 | ["2017-06-21 08:00:00","2017-06-21 13:00:00")
  2 |  2 | ["2017-06-21 08:00:00","2017-06-21 13:00:00")
  3 |  1 | ["2017-06-21 14:00:00","2017-06-21 16:00:00")
  4 |  2 | ["2017-06-21 15:00:00","2017-06-21 18:00:00")
(4 rows)
test=# select *, lower(von_bis)-upper(lag(von_bis) over (partition by lkw order by von_bis)) as pausenzeit from schichten ;
 id | lkw |  von_bis  | pausenzeit
----+-----+-----------------------------------------------+------------
  1 |  1 | ["2017-06-21 08:00:00","2017-06-21 13:00:00") |
  3 |  1 | ["2017-06-21 14:00:00","2017-06-21 16:00:00") | 01:00:00
  2 |  2 | ["2017-06-21 08:00:00","2017-06-21 13:00:00") |
  4 |  2 | ["2017-06-21 15:00:00","2017-06-21 18:00:00") | 02:00:00
(4 rows)

PostgreSQL: Primary & Foreign Keys, TSRANGE-Datentypen, Window-Funktionen. Eines der Feature kann sogar MySQL, finde heraus, welches ;-)
 
Den eleganten Weg hatte ich ja schon gezeigt. MySQL kann keine lag() - Funktione, aber vielleicht findest Du via Google eine Alternative. Alternativ: wirf MySQL weg und nutze PostgreSQL. Wäre die bessere und einfachere Lösung.
 
Werbung:
Hallo,

ich habe mir hier nicht das komplette Problem durchgelesen. Wenn es jedoch nur ein Problem ist an die Zeiten der letzen Zeile zu kommen kannst du mit Variablen arbeiten.

Code:
SELECT
    @last_beginn AS last_begin
    , @last_ende AS last_ende
    , @last_beginn:=beginn AS beginn
    , @last_ende:=ende AS ende
FROM schichten
CROSS JOIN
    (SELECT @last_beginn:=NULL, @last_ende:=NULL) AS init;


Hier einmal ein Beispiel:

Code:
mysql> SELECT * from schichten;
+------------+--------+---------------------+---------------------+
| schicht_id | lkw_id | beginn              | ende                |
+------------+--------+---------------------+---------------------+
|          1 |     11 | 2016-01-01 10:00:00 | 2016-01-01 16:00:00 |
|          2 |     11 | 2016-01-02 08:00:00 | 2016-01-02 14:00:00 |
|          3 |     11 | 2016-01-03 09:00:00 | 2016-01-03 10:00:00 |
+------------+--------+---------------------+---------------------+
3 rows in set (0,00 sec)

mysql> SELECT
    ->     @last_beginn AS last_begin
    ->     , @last_ende AS last_ende
    ->     , @last_beginn:=beginn AS beginn
    ->     , @last_ende:=ende AS ende
    -> FROM schichten
    -> CROSS JOIN
    ->     (SELECT @last_beginn:=NULL, @last_ende:=NULL) AS init;
+---------------------+---------------------+---------------------+---------------------+
| last_begin          | last_ende           | beginn              | ende                |
+---------------------+---------------------+---------------------+---------------------+
| NULL                | NULL                | 2016-01-01 10:00:00 | 2016-01-01 16:00:00 |
| 2016-01-01 10:00:00 | 2016-01-01 16:00:00 | 2016-01-02 08:00:00 | 2016-01-02 14:00:00 |
| 2016-01-02 08:00:00 | 2016-01-02 14:00:00 | 2016-01-03 09:00:00 | 2016-01-03 10:00:00 |
+---------------------+---------------------+---------------------+---------------------+
3 rows in set (0,00 sec)

mysql>

Noch kurz eine Anmerkung:
Window Funktionen sind in MariaDB 10.2 vorhanden und diese ist einfach mit MySQL zu tauschen und auch kompatibel.


Gruss

Bernd
 
Zurück
Oben