Précédent   Forum des professionnels en informatique > Bases de données > MS SQL-Server > Développement
Développement Forum d'entraide sur le Transact-SQL, le CLR, les procédures stockées, les triggers, les requêtes SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 02/03/2011, 17h54   #1
Futur Membre du Club
 
Développeur informatique
Inscription : octobre 2010
Messages : 18
Détails du profil
Informations personnelles :
Localisation : France, Oise (Picardie)

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : octobre 2010
Messages : 18
Points : 15
Points : 15
Par défaut Sommes d'un Time(7)

Bonjour à tous,

J'ai besoin de faire la somme d'un Time(7) dans une requête.

J'ai essayé avec :

SELECT SUM(Act_Duree) AS SommeDuree
FROM Temps

mais cela ne fonctionne pas, j'ai le message d'erreur : Operand data type time is invalid for sum operator.

Comment puis-je faire pour faire la somme ?

D'avance merci

PS : j'ai également testé ceci : -- SELECT SUM(DATEDIFF(MI,'00:00:00', Act_Duree)) AS SommeDuree, mais cela me renvoie un total faux (il ne prend pas en compte les secondes)
stelincat est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/03/2011, 18h20   #2
Membre Expert
 
Inscription : janvier 2010
Messages : 1 084
Détails du profil
Informations personnelles :
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : janvier 2010
Messages : 1 084
Points : 1 573
Points : 1 573
Bonjour

Citation:
Envoyé par stelincat Voir le message
Bonjour à tous,

PS : j'ai également testé ceci : -- SELECT SUM(DATEDIFF(MI,'00:00:00', Act_Duree)) AS SommeDuree, mais cela me renvoie un total faux (il ne prend pas en compte les secondes)
Comment ca un resultat faux ?

si vous utilisez TIME(7), soit une précision à 100 ns, et que vous stockez effectivement des durées a cette précision, ou du moins un précision inférieure à la minute, il est normal que le résultat ne soit pas celui attendu, car DATEDIFF renvoi un nombre entier tronqué.
ainsi :
Code sql :
1
2
 
SELECT DATEDIFF(MI, '00:00:00', '00:01:59')
renvoi 1 et non pas 2
et par la même :
Code sql :
1
2
 
SELECT DATEDIFF(MI, '00:00:00', '00:01:59') + DATEDIFF(MI, '00:00:00', '00:01:59')
renvoi 2 et non pas 3, ni 4...
quand bien même 1min59 + 1min59 font 3min58
ceci peut expliquer que le résultat obtenu n'est pas celui attendu...

Si c'est la cas, changez le datepart de votre fonction DATEDIFF pour un intervalle plus adapté à vos données, en fonction de leur précision
aieeeuuuuu est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 02/03/2011, 19h34   #3
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 684
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 684
Points : 10 459
Points : 10 459
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Il y a un problème de typage de vos données, non ?

TIME permet de stocker les informations horaires d'une date, ce n'est ni une durée ni un intervalle.
Par exemple il est 19h34, c'est bien une information TIME.

Mais quelqu'un qui a travaillé pendant 19h, c'est une durée que vous devez stocker dans un format numérique.
__________________
Email : http://scr.im/waldar
Waldar est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/03/2011, 08h31   #4
Modérateur

 
Avatar de elsuket
 
Homme Nicolas Souquet
Administrateur de base de données
Inscription : janvier 2005
Messages : 4 667
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Souquet
Âge : 30
Localisation : Thaïlande

Informations professionnelles :
Activité : Administrateur de base de données
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : janvier 2005
Messages : 4 667
Points : 8 715
Points : 8 715
Bonjour,

Je doute également que pour un temps de travail vous ayez besoin d'une précision à 100 nanosecondes ...
Vous avez donc utilisé 5 octets au lieu de 3 pour un time(0), pour lequel vous avez une précision à la seconde.

Comme vous avez choisi un type de données qui n'est pas destiné à stocker des durées mais une heure, vous pouvez néanmoins extraire le nombre de secondes (mais est-bien la peine ?) qu'une personne a travaillé dans une nouvelle colonne :

Code :
1
2
3
4
5
6
7
8
9
10
11
ALTER TABLE dbo.maTable
ADD duree_travail_secondes int
GO
 
UPDATE	dbo.maTable
SET	duree_travail_secondes = DATEDIFF(second, CAST('00:00:00' AS time(0)), maColonneTime7)
GO
 
ALTER TABLE dbo.maTable
ALTER COLUMN duree_travail_secondes int NOT NULL
GO
Vous pouvez éventuellement ajouter :

Code :
1
2
ALTER TABLE dbo.maTable
ADD CONSTRAINT CHKmaTable_duree_travail_secondes CHECK (duree_travail_secondes >= 0)
Puis supprimer votre colonne time(7) :

Code :
1
2
ALTER TABLE dbo.maTable
DROP COLUMN maColonneTime7
Il vous faudra malheureusement probablement changer le code de votre application ...

Enfin pour convertir cette durée stockée en secondes en une valeur plus intelligible, vous pouvez écrire :

Code :
1
2
3
4
5
SELECT	autresColonnesDe_maTable
	, CONVERT(varchar(5), duree_travail_secondes / 3600) + ':' + 
		CONVERT(varchar(2), duree_travail_secondes % 3600 / 60) + ':' + 
		CONVERT(varchar(5),(duree_travail_secondes % 60))
FROM	dbo.maTable
Mieux, vous pouvez en faire une fonction.
Si vous voulez l'utiliser pour dans vos requêtes d'interrogation de la table, il vaut mieux écrire une fonction de table en ligne plutôt qu'une fonction scalaire (meilleur en performances), puisqu'une telle fonction ne retourne qu'une ligne.
En effet SQL Server estime toujours qu'une telle fonction retourne une seule ligne

Voici donc la fonction de table en ligne :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CREATE FUNCTION fn_duration_to_hhmmss
	(
		@duration int
	)
	RETURNS TABLE
AS
RETURN	SELECT CONVERT(varchar(5), @duration / 3600) + ':' + 
	CASE LEN(CONVERT(varchar(2), @duration % 3600 / 60))
		WHEN 1 THEN '0' + CONVERT(varchar(2), @duration % 3600 / 60)
		ELSE CONVERT(varchar(2), @duration % 3600 / 60)
	END + ':' + 
	CASE LEN(CONVERT(varchar(2),(@duration % 60)))
		WHEN 1 THEN '0' + CONVERT(varchar(2),(@duration % 60))
		ELSE CONVERT(varchar(5),(@duration % 60))
	END AS hhmmss
Ce qui vous permet d'interroger la table de la façon suivante :

Code :
1
2
3
4
SELECT		T.desColonnesDe_maTable
		, D.hhmmss
FROM		dbo.maTable AS T
CROSS APPLY	dbo.fn_duration_to_hhmmss(T.duree_travail_secondes) AS D
Remplacez CROSS par OUTER si duree_travail_secondes peut être NULL.

@++
__________________
En bases de données relationnelles SQL, il n'y a ni tableaux, ni enregistrements, ni champs: il y a des tables, des lignes et des colonnes.
Blog | Profil| Consulter ou télécharger les fichiers d'aide de SQL Server, des versions 2000 à 2012
elsuket est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 15h13.


 
 
 
 
Partenaires

Hébergement Web