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

Firebird SP Minuten summieren

Dieses Thema im Forum "Andere Datenbankserver" wurde erstellt von lapadula, 26 Juni 2018.

  1. lapadula

    lapadula Benutzer

    Hallo, ich weiss nicht wohin mit dem Thema Firebird, auf Wikipedio steht, dass die Syntax so ähnlich ist wie Oracle, deslhab habe ich das Thema hier eröffnet.

    Es geht um eine Stored Procedure an der ich gerade bastele und nicht weiterkomme.

    Aus einer Tabelle wo alle Zeitstempel aller Mitarbeiter gespeichert werden, soll herausgefunden werden, ob ein bestimmter Mitarbeiter im Plus oder Minus ist.

    Ich habe ein Select womit ich alle Zeitstempel in einem bestimmten Zeitraum und einer bestimmten User_ID abfrage.

    Pro Tag gibt es eine gerade Anzahl an Stempel, sieht folgendermaßen aus:

    02.05.2018, 08:35:06.000
    02.05.2018, 11:58:02.000
    02.05.2018, 12:35:51.000
    02.05.2018, 16:58:30.000
    03.05.2018, 08:37:03.000
    03.05.2018, 12:12:43.000
    03.05.2018, 12:34:47.000
    03.05.2018, 17:02:20.000
    04.05.2018, 08:37:05.000
    04.05.2018, 12:00:55.000
    04.05.2018, 12:29:25.000
    15.05.2018, 08:31:48.000
    15.05.2018, 12:01:27.000
    15.05.2018, 12:18:19.000
    15.05.2018, 16:59:14.000
    15.05.2018, 16:59:20.000


    Ich habe mir überlegt, mit einer Schleife alle Einträge durchzugehen, eine Hilfsvariable hochzuzählen und zu schauen ob diese gerade oder ungerade ist, die Zwischenergebnise aus der Abfrage in einer Hilfsvariable zwischenzuspeichern und die Differenz in Minuten summieren.

    Sieht folgendermaßen aus:

    Code:
    SET TERM ^ ;
    ALTER PROCEDURE SP_ATTENDANT
    RETURNS (
        Datum Timestamp,
        DiffMinuten Integer,
        Ergebnis Integer,
        x Timestamp,
        y Timestamp
        )
    AS
    declare variable i Integer;
    declare variable Summe Integer;
    
    BEGIN
        i = 0;
        Summe = 0;
        FOR SELECT a."WHEN"
            FROM ATTENDANT a
            WHERE cast(a."WHEN" as date) >= '01.05.2018'
                AND cast(a."WHEN" as date) < current_date
                AND a.USERID = 10
            INTO :Datum
        DO
        BEGIN
            i = i + 1;
            if (mod(i, 2) = 0) then
                x = Datum;
            else
                y = Datum;
                
        Summe = Summe + DATEDIFF(MINUTE FROM (x) TO (y));
        END
        Ergebnis = Summe;
        
    END^
    SET TERM ; ^
    
    GRANT EXECUTE
     ON PROCEDURE SP_ATTENDANT TO  SYSDBA;
    
    

    Allerdings bekomme ich beim Ergebnis immer NULL. Ich verstricke mich hier auch in der Schleife, vllt gibt es eine elegantere Methode, da ich auch noch den Tageswechsel mit beachten muss.
     
  2. akretschmer

    akretschmer Datenbank-Guru

    3 Einträge am 4.5., 5 Einträge am 15.5. Wenn ich mich recht an meine Grundschulzeit erinnere, sind 3 und 5 aber ungerade Zahlen.

    Sollen das Kommen-Gehen - Buchungen sein?
     
  3. lapadula

    lapadula Benutzer

    Ups, da habe ich wohl falsch kopiert oder der MA hat sich da falsch eingestempelt, die Zeiterfassung war zu der Zeit neu installiert.

    Zu deiner Frage, ja es sind kommen und gehen Stempel, daher müsste die Anzahl gerade sein. Bei den meisten ist: Kommen, zur Pause, von der Pause und Gehen.

    Es gibt auch einen Feld für 1 kommen und 0 gehen, hilft mir aber auch nicht wirklich weiter.
     
  4. akretschmer

    akretschmer Datenbank-Guru

    Also, ich habe mal Deine Daten in eine Tabelle getan. Die Spalte t nur zum Import, um daraus ts vom Typ "timestamp" zu ermitteln.

    Code:
    test=*# select * from lapadula ;
                t             |         ts         
    --------------------------+---------------------
     02.05.2018, 08:35:06.000 | 2018-05-02 08:35:06
     02.05.2018, 11:58:02.000 | 2018-05-02 11:58:02
     02.05.2018, 12:35:51.000 | 2018-05-02 12:35:51
     02.05.2018, 16:58:30.000 | 2018-05-02 16:58:30
     03.05.2018, 08:37:03.000 | 2018-05-03 08:37:03
     03.05.2018, 12:12:43.000 | 2018-05-03 12:12:43
     03.05.2018, 12:34:47.000 | 2018-05-03 12:34:47
     03.05.2018, 17:02:20.000 | 2018-05-03 17:02:20
     04.05.2018, 08:37:05.000 | 2018-05-04 08:37:05
     04.05.2018, 12:00:55.000 | 2018-05-04 12:00:55
     04.05.2018, 12:29:25.000 | 2018-05-04 12:29:25
     15.05.2018, 08:31:48.000 | 2018-05-15 08:31:48
     15.05.2018, 12:01:27.000 | 2018-05-15 12:01:27
     15.05.2018, 12:18:19.000 | 2018-05-15 12:18:19
     15.05.2018, 16:59:14.000 | 2018-05-15 16:59:14
     15.05.2018, 16:59:20.000 | 2018-05-15 16:59:20
    (16 Zeilen)
    
    Nun kann man mit Window-Funktionen (ich weiß nicht, ob Firebird das kann) die Zeiten berechnen:

    Code:
    test=*# with tmp as (select ts, case when (row_number() over (partition by ts::date))%2 = 1 then 'kommt' else 'geht' end as buchung from lapadula) select *, case when buchung = 'geht' then ts-lag(ts) over (order by ts) end as zeit from tmp ;
             ts          | buchung |   zeit   
    ---------------------+---------+----------
     2018-05-02 08:35:06 | kommt   |
     2018-05-02 11:58:02 | geht    | 03:22:56
     2018-05-02 12:35:51 | kommt   |
     2018-05-02 16:58:30 | geht    | 04:22:39
     2018-05-03 08:37:03 | kommt   |
     2018-05-03 12:12:43 | geht    | 03:35:40
     2018-05-03 12:34:47 | kommt   |
     2018-05-03 17:02:20 | geht    | 04:27:33
     2018-05-04 08:37:05 | kommt   |
     2018-05-04 12:00:55 | geht    | 03:23:50
     2018-05-04 12:29:25 | kommt   |
     2018-05-15 08:31:48 | kommt   |
     2018-05-15 12:01:27 | geht    | 03:29:39
     2018-05-15 12:18:19 | kommt   |
     2018-05-15 16:59:14 | geht    | 04:40:55
     2018-05-15 16:59:20 | kommt   |
    (16 Zeilen)
    
    test=*#
    
    Kann man natürlich noch zusammenfassen:
    Code:
    test=*# with tmp as (select ts, case when (row_number() over (partition by ts::date))%2 = 1 then 'kommt' else 'geht' end as buchung from lapadula), tmp2 as ( select *, case when buchung = 'geht' then ts-lag(ts) over (order by ts) end as zeit from tmp ) select ts::date, sum(zeit) from tmp2 group by ts::date;
         ts     |   sum   
    ------------+----------
     2018-05-15 | 08:10:34
     2018-05-04 | 03:23:50
     2018-05-03 | 08:03:13
     2018-05-02 | 07:45:35
    (4 Zeilen)
    
    test=*#
    
    So schön kann SQL sein, ohne stored Procs oder so ;-)
     
  5. lapadula

    lapadula Benutzer

    Danke für deine Hilfe, ich werde mal versuchen das in Firebird zu verwursten.
     
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