Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

Ausgabe eines Query anders als erwartet

Dieses Thema im Forum "MySQL und MariaDB" wurde erstellt von Fuxxy1979, 21 Juni 2017.

  1. Fuxxy1979

    Fuxxy1979 Benutzer

    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.
     
  2. akretschmer

    akretschmer Datenbank-Guru

    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.
     
  3. Fuxxy1979

    Fuxxy1979 Benutzer

    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?
     
  4. akretschmer

    akretschmer Datenbank-Guru

    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.
     
  5. Fuxxy1979

    Fuxxy1979 Benutzer

    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?
     
  6. Matthi

    Matthi Benutzer

    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
     
  7. Fuxxy1979

    Fuxxy1979 Benutzer

    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.
     
  8. Matthi

    Matthi Benutzer

    Wenn ich das richtig verstanden habe:

    SELECT TIMEDIFF(ende,beginn) as t, lkw_id FROM
    schichten GROUP BY t,lkw_id
     
  9. akretschmer

    akretschmer Datenbank-Guru

    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 ;-)
     
  10. Fuxxy1979

    Fuxxy1979 Benutzer

    ALTER TABLE `schichten`
    ADD CONSTRAINT `schichten_ibfk_1` FOREIGN KEY (`lkw_id`) REFERENCES `lkw` (`lkw_id`);
    COMMIT;
     
  11. Fuxxy1979

    Fuxxy1979 Benutzer

    Das würde für die Schichtzeiten passen, mein Problem liegt bei den Ruhepausen.
    Aber vielleicht habe ich gerade einen Anhaltspunkt bekommen
     
  12. Fuxxy1979

    Fuxxy1979 Benutzer

    Leider hat der Anhaltspunkt bei mir in Leere gegriffen, komme immer noch nicht weiter.
     
  13. akretschmer

    akretschmer Datenbank-Guru

    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.
     
  14. Fuxxy1979

    Fuxxy1979 Benutzer

    Ich installiere es gerade, um es zu testen. Du hast ja oben schon etwas gepostet.
     
    akretschmer gefällt das.
  15. BerndB

    BerndB Datenbank-Guru

    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
     
    Coolia und ukulele gefällt das.
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden