IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Bases de données Delphi Discussion :

Calcul de somme dans un champ de type Time ou Timestamp avec Firebird


Sujet :

Bases de données Delphi

  1. #1
    Membre averti Avatar de Feymann
    Femme Profil pro
    Automaticienne - informaticienne industrielle
    Inscrit en
    Juillet 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Automaticienne - informaticienne industrielle
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2012
    Messages : 27
    Par défaut Calcul de somme dans un champ de type Time ou Timestamp avec Firebird
    Bonjour,

    Malgré les nombreuses pistes du forum, je n'ai pas vraiment trouvé de solution à mon problème.

    Dans une table de base de données Firebird (2.5), j'essaie de calculer une somme de durées. Il s'agit d'une table de pointage des heures de travail. Parmi les champs de ma table, j'en ai un qui contient déjà la durée journalière du travail (en format hh:mm:ss), donc je ne travaille pas avec une date de début et une date de fin. La durée par jour est déjà calculée.

    Je voudrais simplement calculer le nombre d'heures travaillées par semaine, mais j'ai un problème sur le calcul de la somme, à cause du format de ce champ "durée réelle". J'ai essayé en type Time et en type Timestamp.

    Ma requête est du genre:
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT ANNEE,SEMAINE, SUM(DUREE_REELLE) as TOTAL FROM POINTAGE2
    Group by ANNEE, SEMAINE ORDER BY ANNEE, SEMAINE ASC;

    Forcément il ne peut pas calculer la somme et j'ai l'erreur :"Argument for SUM in dialect 3 must be numeric". Si je fais la somme sur un autre champ type integer, alors ça marche.
    Malheureusement les fonctions genre Time_To_Sec n'existe pas dans Firebird, j'ai essayé de faire des CAST, mais ça ne marche pas non plus.
    Y a-t-il un moyen simple, sans faire une usine à gaz avec des conversions pour calculer cette somme?

    Merci d'avance pour votre réponse.

  2. #2
    Membre éclairé
    Avatar de FOCUS77
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2014
    Messages
    336
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2014
    Messages : 336
    Par défaut
    Bonjour à tous,

    @Feymann
    Pourquoi ne pas utiliser un champ persistant de type integer?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    procedure TForm1.SQLQuery1CalcFields(DataSet: TDataSet);
    begin
     SQLQUERY1.FieldValues['NBR_HEURE']:= SQLQUERY1.FieldValues['DUREE_REELLE']/StrToTime('01:00:00') ;
    end;

  3. #3
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 706
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 706
    Billets dans le blog
    65
    Par défaut
    Bonjour,

    C'est plus un problème Firebird que Delphi me semble t-il.
    tout d'abord pour obtenir un temps en secondes entre deux dates il y a la fonction interne DateDiff note : DateDiff fonctionne aussi pour les types TIME

    Parmi les champs de ma table, j'en ai un qui contient déjà la durée journalière du travail (en format hh:mm:ss), donc je ne travaille pas avec une date de début et une date de fin. La durée par jour est déjà calculée.
    A mon avis l'erreur est d'avoir utilisé une colonne de type TIME et non pas directement un numérique mais bon voici la solution SQL

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT ANNEE,SEMAINE, SUM(DATEDIF(SECOND,TIME '0:00',DUREE_REELLE) as TOTAL FROM POINTAGE2
    Group by ANNEE, SEMAINE ORDER BY ANNEE, SEMAINE ASC;

  4. #4
    Membre averti Avatar de Feymann
    Femme Profil pro
    Automaticienne - informaticienne industrielle
    Inscrit en
    Juillet 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Automaticienne - informaticienne industrielle
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2012
    Messages : 27
    Par défaut
    Bonjour,

    Merci FOCUS77 et SergioMaster pour vos réponses.
    Je vais essayer la solution Datediff (ce soir car je suis au travail).

    Mais j'ai aussi la possibilité de transformer mon champs DUREE_REELLE en numérique. Les données de pointage, je les récupère depuis une appli smartphone sous forme d'Export csv, donc j'en fais ce que je veux. Je l'ai formaté ainsi car c'est plus "lisible" côté BDD. Mais ce n'est pas grave, Delphi me formatera comme je le voudrai.

  5. #5
    Membre averti Avatar de Feymann
    Femme Profil pro
    Automaticienne - informaticienne industrielle
    Inscrit en
    Juillet 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Automaticienne - informaticienne industrielle
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2012
    Messages : 27
    Par défaut
    Rebonjour,

    J'ai donc essayé la requête suivante:

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT ANNEE,SEMAINE, SUM(DATEDIFF(SECOND, TIME '0:00',DUREE_REELLE)) as TOTAL FROM POINTAGE
    Group by ANNEE, SEMAINE ORDER BY ANNEE, SEMAINE ASC;

    Ça fonctionne bien sur la table où mon champ duree_reelle est de type Time (et pas Timestamp que j'ai essayé aussi).
    Pour le remettre en forme sous Delphi c'est un détail après.

    Merci encore une fois.

  6. #6
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 706
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 706
    Billets dans le blog
    65
    Par défaut
    Citation Envoyé par Feymann Voir le message
    Ça fonctionne bien sur la table où mon champ duree_reelle est de type Time (et pas Timestamp que j'ai essayé aussi).
    Logique, avec un TimeStamp, donc contenant aussi la Date il aurait fallu changer le TIME '0:00' en un TIMESTAMP , récupérer la partie Date de la colonne, retransformer cette partie en TimeStamp par un CAST pour faire le DateDiff

    Le mieux reste néanmoins de définir la colonne DUREE_REELLE en BIGINT (secondes)

  7. #7
    Membre averti Avatar de Feymann
    Femme Profil pro
    Automaticienne - informaticienne industrielle
    Inscrit en
    Juillet 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Automaticienne - informaticienne industrielle
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2012
    Messages : 27
    Par défaut
    Bonjour,

    Merci pour le conseil. Ça marche aussi en Bigint.
    Toutefois je préfère la première solution, car non seulement je fais des statistiques, mais j'affiche le contenu de la table dans un DBGrid et '05:07:00' est plus lisible que 18420. Après je peux toujours formater mon champs...

  8. #8
    Membre éclairé
    Avatar de FOCUS77
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2014
    Messages
    336
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2014
    Messages : 336
    Par défaut
    Bonsoir à tous,

    J'ai voulu afficher le nombre 'TOTAL' sous forme d'heures, minutes et secondes, à l'aide de ce code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     procedure TForm1.Button1Click(Sender: TObject);
    var d,h,m,s:integer;
    begin
       if Query.active=false then
       Query.active:=true;
      d:=Query.FieldValues['TOTAL'];
     
    s:=d mod 60;
    m:=((d-s) mod 3600)div 60;
    h:=(d-m-s) div 3600;
    ShowMessage(IntToStr(h)+' heures'+', '+IntToStr(m)+' minutes et '+IntToStr(s)+' secondes');
    end;

  9. #9
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 706
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 706
    Billets dans le blog
    65
    Par défaut
    Bonjour,
    Citation Envoyé par Feymann Voir le message
    Ça marche aussi en Bigint.
    pour le sum, bien évidement
    Toutefois je préfère la première solution, car non seulement je fais des statistiques, mais j'affiche le contenu de la table dans un DBGrid et '05:07:00' est plus lisible que 18420.
    Je l'ai formaté ainsi car c'est plus "lisible" côté BDD.
    justement non et c'est là où mon avis diverge. Le stockage dans une base de données n'est pas fait pour avoir des "formatages". Pour moi une durée est un intervalle de temps exprimé selon les besoins en minutes ou en secondes ou en millièmes de seconde voir en centièmes de minutes (je suis aussi dans l'industrie avec des gammes opératoires en centièmes pour corser)


    Après je peux toujours formater mon champs...
    exactement, mais il y a aussi une solution SQL par exemple, si la durée est en minute

    ET SI LA DUREE NE DEPASSE PAS 24 HEURES

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT DATEADD( minute,a.DUREE,CAST('0:00' AS Time))
    FROM TABLE
    nous revoilà avec une colonne en "temps" affichable

    pour répondre à FOCUS77 une autre manière de faire ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    procedure TForm8.Button1Click(Sender: TObject);
    var H : TDateTime;
    begin
      H:=IncMinute(0,FDQuery1.FieldByname('DUREE').AsInteger);
      Label1.Caption:=TimeTostr(h);
    end;
    A fortiori, une statistique (un sum sur la durée) risque de déborder des 24 heures
    dans ce cas un simple Format('%4d:%.2d',[Duree div 60,Duree mod 60]); donne quelque chose de "lisible"

  10. #10
    Membre averti Avatar de Feymann
    Femme Profil pro
    Automaticienne - informaticienne industrielle
    Inscrit en
    Juillet 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Automaticienne - informaticienne industrielle
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2012
    Messages : 27
    Par défaut
    Bonjour,

    Merci encore une fois SergioMaster.
    Vous avez raison, je vais rester à la version de champ en Bigint, c'est mieux pour une base de données et ce sera plus propre pour travailler quel que soit le type de traitement.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 10/03/2016, 08h59
  2. [AC-2010] Somme dans un champ calculé
    Par nrdz83 dans le forum Access
    Réponses: 2
    Dernier message: 19/01/2014, 19h21
  3. [AC-2007] Comment calculer la somme de 3 champ sur 4 dans un graphique
    Par rch05 dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 17/02/2011, 17h55
  4. Réponses: 7
    Dernier message: 29/11/2010, 13h26
  5. Réponses: 2
    Dernier message: 13/03/2007, 17h57

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo