OVH Cloud OVH Cloud

Pb de Requete. Un petit problème à résoudre

7 réponses
Avatar
FAUCHILLE Stéphan
Bonjour à tous

J'ai une Table me permettant d'historiser les états de marche et d'arrêt
d'un moteur. A chaque fois qu'il se met en marche ou s'arrête, un message
est enregistré.

Id DateHeure Valeur(0=Arret;1=Marche)
1 18/11/2003 12:00:00 0
2 18/11/2003 12:45:00 1
3 18/11/2003 14:55:00 0
4 18/11/2003 15:00:00 1
5 19/11/2003 12:00:00 0
6 19/11/2003 18:00:00 1

Voila la table avec des valeurs.

Maintenant je souhaite connaitre le temps de marche (ou d'arrêt) du moteur
entre deux dates.

Par exemple le temps de marche du moteur entre le 18/11/2003 12:10:00 et
19/11/2003 11:00:00

Comment puis-je faire?

Si vous avez des idées.

D'avance merci et bon courage.

Stef

7 réponses

Avatar
Fred BROUARD
bonjour

CREATE TABLE T_MOTEUR
(ID INT,
DATEHEURE DATETIME,
VALEUR BIT)

INSERT INTO T_MOTEUR VALUES (1, '18/11/2003 12:00:00', 0)
INSERT INTO T_MOTEUR VALUES (2, '18/11/2003 12:45:00', 1)
INSERT INTO T_MOTEUR VALUES (3, '18/11/2003 14:55:00', 0)
INSERT INTO T_MOTEUR VALUES (4, '18/11/2003 15:00:00', 1)
INSERT INTO T_MOTEUR VALUES (5, '19/11/2003 12:00:00', 0)
INSERT INTO T_MOTEUR VALUES (6, '19/11/2003 18:00:00', 1)

1ere phase : retrouver pour chaque ligne la suivante (début et fin) :

SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1

DHD DHF VALEUR
------------------------- ------------------------ ------
2003-11-18 12:00:00.000 2003-11-18 12:45:00.000 0
2003-11-18 12:45:00.000 2003-11-18 14:55:00.000 1
2003-11-18 14:55:00.000 2003-11-18 15:00:00.000 0
2003-11-18 15:00:00.000 2003-11-19 12:00:00.000 1
2003-11-19 12:00:00.000 2003-11-19 18:00:00.000 0
2003-11-19 18:00:00.000 NULL 1

Cette table peut maintenant être reprise dans la clause FROM d'une
nouvelle pour calcul :

SELECT DHF - DHD AS DUREE, VALEUR
FROM
(
SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1
) TT


DUREE VALEUR
------------------------------------------------------ ------
1900-01-01 00:45:00.000 0
1900-01-01 02:10:00.000 1
1900-01-01 00:05:00.000 0
1900-01-01 21:00:00.000 1
1900-01-01 06:00:00.000 0
NULL 1

Mais la réponse fait apparaitres des dates au liue de temps. Pour cela
transtypons en float :

SELECT CAST(DHF - DHD AS FLOAT) AS DUREE_JOUR, VALEUR
FROM
(
SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1
) TT

DUREE_JOUR VALEUR
----------------------------------------------------- ------
0.03125 0
9.0277777777777776E-2 1
3.4722222222222225E-3 0
0.875 1
0.25 0
NULL 1

Et pour obtenir des heures décimales :

SELECT CAST(DHF - DHD AS FLOAT) * 24 AS DUREE_H, VALEUR
FROM
(
SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1
) TT

DUREE_H VALEUR
----------------------------------------------------- ------
0.75 0
2.1666666666666665 1
8.3333333333333343E-2 0
21.0 1
6.0 0
NULL 1

En ajoutant cette fonction, nous avons les heures décimales converties
en HMS :

CREATE FUNCTION FN_CONVERT_HD_HMS (@HD FLOAT)
RETURNS VARCHAR(8)
AS

BEGIN

DECLARE @H INTEGER
DECLARE @M INTEGER
DECLARE @S INTEGER
DECLARE @RETVAL VARCHAR(8)

-- cas trivial
IF @HD IS NULL
RETURN NULL

-- récupération des heures, minutes, secondes
SET @H = FLOOR(@HD)
SET @HD = @HD - @H
SET @HD = @HD * 60
SET @M = FLOOR(@HD)
SET @HD = @HD - @M
SET @HD = @HD * 60
SET @S = FLOOR(@HD)

IF @H < 10
SET @RETVAL = '0'+CAST(@H AS CHAR(1))+':'
ELSE
SET @RETVAL = CAST(@H AS CHAR(2))+':'
IF @M < 10
SET @RETVAL = @RETVAL + '0' + CAST(@M AS CHAR(1))+':'
ELSE
SET @RETVAL = @RETVAL + CAST(@M AS CHAR(2))+':'
IF @S < 10
SET @RETVAL = @RETVAL + '0' + CAST(@S AS CHAR(1))
ELSE
SET @RETVAL = @RETVAL + CAST(@S AS CHAR(2))+':'

RETURN @RETVAL

END

La requête avec la fonction :

SELECT dbo.FN_CONVERT_HD_HMS (CAST(DHF - DHD AS FLOAT) * 24)
AS DUREE_HMS, VALEUR
FROM
(
SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1
) TT

Le résultat :

DUREE_HMS VALEUR
---------- ------
00:45:00 0
02:09:59 1
00:05:00 0
21:00:00 1
06:00:00 0
NULL 1

etc...


Libre à toi après de faire un cumul (SUM) entre deux datetime (BETWEEN)
passées en paramètres...


A +



--
Frédéric BROUARD - expert SQL, spécialiste : SQL Server / Delphi / web
Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html
Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com
****************** mailto: ******************

FAUCHILLE Stéphan a écrit:
Bonjour à tous

J'ai une Table me permettant d'historiser les états de marche et d'arrêt
d'un moteur. A chaque fois qu'il se met en marche ou s'arrête, un message
est enregistré.

Id DateHeure Valeur(0=Arret;1=Marche)
1 18/11/2003 12:00:00 0
2 18/11/2003 12:45:00 1
3 18/11/2003 14:55:00 0
4 18/11/2003 15:00:00 1
5 19/11/2003 12:00:00 0
6 19/11/2003 18:00:00 1

Voila la table avec des valeurs.

Maintenant je souhaite connaitre le temps de marche (ou d'arrêt) du moteur
entre deux dates.

Par exemple le temps de marche du moteur entre le 18/11/2003 12:10:00 et
19/11/2003 11:00:00

Comment puis-je faire?

Si vous avez des idées.

D'avance merci et bon courage.

Stef




Avatar
FAUCHILLE Stéphan
Je suis impressionné, ça faisait longtemps que je cherchais une réponse
simple. J'avais déjà une solution mais avec un crossjoin, puis suppression
des doublons, etc... mais très gourmandes en temps.

Merci beaucoup

Merci beaucoup de ton aide
"Fred BROUARD" a écrit dans le message news:

bonjour

CREATE TABLE T_MOTEUR
(ID INT,
DATEHEURE DATETIME,
VALEUR BIT)

INSERT INTO T_MOTEUR VALUES (1, '18/11/2003 12:00:00', 0)
INSERT INTO T_MOTEUR VALUES (2, '18/11/2003 12:45:00', 1)
INSERT INTO T_MOTEUR VALUES (3, '18/11/2003 14:55:00', 0)
INSERT INTO T_MOTEUR VALUES (4, '18/11/2003 15:00:00', 1)
INSERT INTO T_MOTEUR VALUES (5, '19/11/2003 12:00:00', 0)
INSERT INTO T_MOTEUR VALUES (6, '19/11/2003 18:00:00', 1)

1ere phase : retrouver pour chaque ligne la suivante (début et fin) :

SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1

DHD DHF VALEUR
------------------------- ------------------------ ------
2003-11-18 12:00:00.000 2003-11-18 12:45:00.000 0
2003-11-18 12:45:00.000 2003-11-18 14:55:00.000 1
2003-11-18 14:55:00.000 2003-11-18 15:00:00.000 0
2003-11-18 15:00:00.000 2003-11-19 12:00:00.000 1
2003-11-19 12:00:00.000 2003-11-19 18:00:00.000 0
2003-11-19 18:00:00.000 NULL 1

Cette table peut maintenant être reprise dans la clause FROM d'une
nouvelle pour calcul :

SELECT DHF - DHD AS DUREE, VALEUR
FROM
(
SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1
) TT


DUREE VALEUR
------------------------------------------------------ ------
1900-01-01 00:45:00.000 0
1900-01-01 02:10:00.000 1
1900-01-01 00:05:00.000 0
1900-01-01 21:00:00.000 1
1900-01-01 06:00:00.000 0
NULL 1

Mais la réponse fait apparaitres des dates au liue de temps. Pour cela
transtypons en float :

SELECT CAST(DHF - DHD AS FLOAT) AS DUREE_JOUR, VALEUR
FROM
(
SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1
) TT

DUREE_JOUR VALEUR
----------------------------------------------------- ------
0.03125 0
9.0277777777777776E-2 1
3.4722222222222225E-3 0
0.875 1
0.25 0
NULL 1

Et pour obtenir des heures décimales :

SELECT CAST(DHF - DHD AS FLOAT) * 24 AS DUREE_H, VALEUR
FROM
(
SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1
) TT

DUREE_H VALEUR
----------------------------------------------------- ------
0.75 0
2.1666666666666665 1
8.3333333333333343E-2 0
21.0 1
6.0 0
NULL 1

En ajoutant cette fonction, nous avons les heures décimales converties
en HMS :

CREATE FUNCTION FN_CONVERT_HD_HMS (@HD FLOAT)
RETURNS VARCHAR(8)
AS

BEGIN

DECLARE @H INTEGER
DECLARE @M INTEGER
DECLARE @S INTEGER
DECLARE @RETVAL VARCHAR(8)

-- cas trivial
IF @HD IS NULL
RETURN NULL

-- récupération des heures, minutes, secondes
SET @H = FLOOR(@HD)
SET @HD = @HD - @H
SET @HD = @HD * 60
SET @M = FLOOR(@HD)
SET @HD = @HD - @M
SET @HD = @HD * 60
SET @S = FLOOR(@HD)

IF @H < 10
SET @RETVAL = '0'+CAST(@H AS CHAR(1))+':'
ELSE
SET @RETVAL = CAST(@H AS CHAR(2))+':'
IF @M < 10
SET @RETVAL = @RETVAL + '0' + CAST(@M AS CHAR(1))+':'
ELSE
SET @RETVAL = @RETVAL + CAST(@M AS CHAR(2))+':'
IF @S < 10
SET @RETVAL = @RETVAL + '0' + CAST(@S AS CHAR(1))
ELSE
SET @RETVAL = @RETVAL + CAST(@S AS CHAR(2))+':'

RETURN @RETVAL

END

La requête avec la fonction :

SELECT dbo.FN_CONVERT_HD_HMS (CAST(DHF - DHD AS FLOAT) * 24)
AS DUREE_HMS, VALEUR
FROM
(
SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1
) TT

Le résultat :

DUREE_HMS VALEUR
---------- ------
00:45:00 0
02:09:59 1
00:05:00 0
21:00:00 1
06:00:00 0
NULL 1

etc...


Libre à toi après de faire un cumul (SUM) entre deux datetime (BETWEEN)
passées en paramètres...


A +



--
Frédéric BROUARD - expert SQL, spécialiste : SQL Server / Delphi / web
Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html
Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com
****************** mailto: ******************

FAUCHILLE Stéphan a écrit:
> Bonjour à tous
>
> J'ai une Table me permettant d'historiser les états de marche et d'arrêt
> d'un moteur. A chaque fois qu'il se met en marche ou s'arrête, un


message
> est enregistré.
>
> Id DateHeure Valeur(0=Arret;1=Marche)
> 1 18/11/2003 12:00:00 0
> 2 18/11/2003 12:45:00 1
> 3 18/11/2003 14:55:00 0
> 4 18/11/2003 15:00:00 1
> 5 19/11/2003 12:00:00 0
> 6 19/11/2003 18:00:00 1
>
> Voila la table avec des valeurs.
>
> Maintenant je souhaite connaitre le temps de marche (ou d'arrêt) du


moteur
> entre deux dates.
>
> Par exemple le temps de marche du moteur entre le 18/11/2003 12:10:00 et
> 19/11/2003 11:00:00
>
> Comment puis-je faire?
>
> Si vous avez des idées.
>
> D'avance merci et bon courage.
>
> Stef
>
>



Avatar
FAUCHILLE Stéphan
Désolé de revenir à la charge, j'ai essayé ta requete qui marche très bien,
sauf que j'ai dans ma table des cas particuliers

Je peux avoir

Id DateHeure Valeur(0=Arret;1=Marche)
1 18/11/2003 12:00:00 0
7 18/11/2003 12:30:00 0
2 18/11/2003 12:45:00 1
3 18/11/2003 14:55:00 0
4 18/11/2003 15:00:00 1
5 19/11/2003 12:00:00 0
6 19/11/2003 18:00:00 1

En cas de coupure de la base et de redémarrage, elle enregistre de nouveau
le point, donc je peux me retrouver avec 2 mêmes valeurs. Et là le cumul
n'est pas juste.

Autres soucis, est-ce que ça marche si je demande le temps de marche entre
deux valeurs qui ne sont pas des points enregistré, je m'explique :
- Si je fais ma requête entre 18/11/2003 12:15:30 et 18/11/2003 14:58:11

Désolée de te déranger ;-)

Merci

"Fred BROUARD" a écrit dans le message news:

bonjour

CREATE TABLE T_MOTEUR
(ID INT,
DATEHEURE DATETIME,
VALEUR BIT)

INSERT INTO T_MOTEUR VALUES (1, '18/11/2003 12:00:00', 0)
INSERT INTO T_MOTEUR VALUES (2, '18/11/2003 12:45:00', 1)
INSERT INTO T_MOTEUR VALUES (3, '18/11/2003 14:55:00', 0)
INSERT INTO T_MOTEUR VALUES (4, '18/11/2003 15:00:00', 1)
INSERT INTO T_MOTEUR VALUES (5, '19/11/2003 12:00:00', 0)
INSERT INTO T_MOTEUR VALUES (6, '19/11/2003 18:00:00', 1)

1ere phase : retrouver pour chaque ligne la suivante (début et fin) :

SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1

DHD DHF VALEUR
------------------------- ------------------------ ------
2003-11-18 12:00:00.000 2003-11-18 12:45:00.000 0
2003-11-18 12:45:00.000 2003-11-18 14:55:00.000 1
2003-11-18 14:55:00.000 2003-11-18 15:00:00.000 0
2003-11-18 15:00:00.000 2003-11-19 12:00:00.000 1
2003-11-19 12:00:00.000 2003-11-19 18:00:00.000 0
2003-11-19 18:00:00.000 NULL 1

Cette table peut maintenant être reprise dans la clause FROM d'une
nouvelle pour calcul :

SELECT DHF - DHD AS DUREE, VALEUR
FROM
(
SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1
) TT


DUREE VALEUR
------------------------------------------------------ ------
1900-01-01 00:45:00.000 0
1900-01-01 02:10:00.000 1
1900-01-01 00:05:00.000 0
1900-01-01 21:00:00.000 1
1900-01-01 06:00:00.000 0
NULL 1

Mais la réponse fait apparaitres des dates au liue de temps. Pour cela
transtypons en float :

SELECT CAST(DHF - DHD AS FLOAT) AS DUREE_JOUR, VALEUR
FROM
(
SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1
) TT

DUREE_JOUR VALEUR
----------------------------------------------------- ------
0.03125 0
9.0277777777777776E-2 1
3.4722222222222225E-3 0
0.875 1
0.25 0
NULL 1

Et pour obtenir des heures décimales :

SELECT CAST(DHF - DHD AS FLOAT) * 24 AS DUREE_H, VALEUR
FROM
(
SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1
) TT

DUREE_H VALEUR
----------------------------------------------------- ------
0.75 0
2.1666666666666665 1
8.3333333333333343E-2 0
21.0 1
6.0 0
NULL 1

En ajoutant cette fonction, nous avons les heures décimales converties
en HMS :

CREATE FUNCTION FN_CONVERT_HD_HMS (@HD FLOAT)
RETURNS VARCHAR(8)
AS

BEGIN

DECLARE @H INTEGER
DECLARE @M INTEGER
DECLARE @S INTEGER
DECLARE @RETVAL VARCHAR(8)

-- cas trivial
IF @HD IS NULL
RETURN NULL

-- récupération des heures, minutes, secondes
SET @H = FLOOR(@HD)
SET @HD = @HD - @H
SET @HD = @HD * 60
SET @M = FLOOR(@HD)
SET @HD = @HD - @M
SET @HD = @HD * 60
SET @S = FLOOR(@HD)

IF @H < 10
SET @RETVAL = '0'+CAST(@H AS CHAR(1))+':'
ELSE
SET @RETVAL = CAST(@H AS CHAR(2))+':'
IF @M < 10
SET @RETVAL = @RETVAL + '0' + CAST(@M AS CHAR(1))+':'
ELSE
SET @RETVAL = @RETVAL + CAST(@M AS CHAR(2))+':'
IF @S < 10
SET @RETVAL = @RETVAL + '0' + CAST(@S AS CHAR(1))
ELSE
SET @RETVAL = @RETVAL + CAST(@S AS CHAR(2))+':'

RETURN @RETVAL

END

La requête avec la fonction :

SELECT dbo.FN_CONVERT_HD_HMS (CAST(DHF - DHD AS FLOAT) * 24)
AS DUREE_HMS, VALEUR
FROM
(
SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1
) TT

Le résultat :

DUREE_HMS VALEUR
---------- ------
00:45:00 0
02:09:59 1
00:05:00 0
21:00:00 1
06:00:00 0
NULL 1

etc...


Libre à toi après de faire un cumul (SUM) entre deux datetime (BETWEEN)
passées en paramètres...


A +



--
Frédéric BROUARD - expert SQL, spécialiste : SQL Server / Delphi / web
Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html
Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com
****************** mailto: ******************

FAUCHILLE Stéphan a écrit:
> Bonjour à tous
>
> J'ai une Table me permettant d'historiser les états de marche et d'arrêt
> d'un moteur. A chaque fois qu'il se met en marche ou s'arrête, un


message
> est enregistré.
>
> Id DateHeure Valeur(0=Arret;1=Marche)
> 1 18/11/2003 12:00:00 0
> 2 18/11/2003 12:45:00 1
> 3 18/11/2003 14:55:00 0
> 4 18/11/2003 15:00:00 1
> 5 19/11/2003 12:00:00 0
> 6 19/11/2003 18:00:00 1
>
> Voila la table avec des valeurs.
>
> Maintenant je souhaite connaitre le temps de marche (ou d'arrêt) du


moteur
> entre deux dates.
>
> Par exemple le temps de marche du moteur entre le 18/11/2003 12:10:00 et
> 19/11/2003 11:00:00
>
> Comment puis-je faire?
>
> Si vous avez des idées.
>
> D'avance merci et bon courage.
>
> Stef
>
>



Avatar
Fred BROUARD
Re,

CREATE TABLE T_MOTEUR
(ID INT,
DATEHEURE DATETIME,
VALEUR BIT)

INSERT INTO T_MOTEUR VALUES (1, '18/11/2003 12:00:00', 0)
INSERT INTO T_MOTEUR VALUES (2, '18/11/2003 12:45:00', 1)
INSERT INTO T_MOTEUR VALUES (3, '18/11/2003 14:55:00', 0)
INSERT INTO T_MOTEUR VALUES (4, '18/11/2003 15:00:00', 1)
INSERT INTO T_MOTEUR VALUES (5, '19/11/2003 12:00:00', 0)
INSERT INTO T_MOTEUR VALUES (6, '19/11/2003 18:00:00', 1)
INSERT INTO T_MOTEUR VALUES (7, '18/11/2003 12:30:00', 0)

--1ere phase : retrouver pour chaque ligne la suivante (début et fin) :


CREATE VIEW V_MOTEUR_TEMPS
AS
SELECT ID, DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1

SELECT *
FROM V_MOTEUR_TEMPS
ORDER BY 2


ID DHD DHF VALEUR
---- ------------------------- ------------------------ ------
1 2003-11-18 12:00:00.000 2003-11-18 12:45:00.000 0
7 2003-11-18 12:30:00.000 2003-11-18 12:45:00.000 0
2 2003-11-18 12:45:00.000 2003-11-18 14:55:00.000 1
3 2003-11-18 14:55:00.000 2003-11-18 15:00:00.000 0
4 2003-11-18 15:00:00.000 2003-11-19 12:00:00.000 1
5 2003-11-19 12:00:00.000 2003-11-19 18:00:00.000 0
6 2003-11-19 18:00:00.000 NULL 1

-- créons une seconde vue encapsulant la durée :

CREATE VIEW V_MOTEUR_DUREE
AS
SELECT ID, DHD, DHF, VALEUR, CAST(DHF-DHD AS FLOAT) * 24 AS DUREE_HD
FROM V_MOTEUR_TEMPS

SELECT *
FROM V_MOTEUR_DUREE
ORDER BY DHD

-- dès lors il faut trouver la durée maximale de chaque ligne pour la
même fin :

SELECT DHF, MAX(DUREE_HD)
FROM V_MOTEUR_DUREE
GROUP BY DHF
ORDER BY DHF

DHF DUREE_HD

------------------------ -------------------------
NULL NULL
2003-11-18 12:45:00.000 0.75
2003-11-18 14:55:00.000 2.1666666666666665
2003-11-18 15:00:00.000 8.3333333333333343E-2
2003-11-19 12:00:00.000 21.0
2003-11-19 18:00:00.000 6.0


-- puis faire une jointure entre cette requête et la vue durée :

SELECT T1.*
FROM V_MOTEUR_DUREE T1
INNER JOIN (SELECT DHF, MAX(DUREE_HD) AS DUREE_HD
FROM V_MOTEUR_DUREE
GROUP BY DHF) T2
ON T1.DHF = T2.DHF
AND T1.DUREE_HD = T2.DUREE_HD

ID DHD DHF VALEUR DUREE_HD

----- ------------------------ ------------------------ ------ ------
1 2003-11-18 12:00:00.000 2003-11-18 12:45:00.000 0 0.75

2 2003-11-18 12:45:00.000 2003-11-18 14:55:00.000 1 2.167
3 2003-11-18 14:55:00.000 2003-11-18 15:00:00.000 0 8.33E-2
4 2003-11-18 15:00:00.000 2003-11-19 12:00:00.000 1 21.0

5 2003-11-19 12:00:00.000 2003-11-19 18:00:00.000 0 6.0

le reste suit comme lors de mon premier mail...


A lire :
http://sqlpro.developpez.com/Planning/SQL_PLN.html

A +


--
Frédéric BROUARD - expert SQL, spécialiste : SQL Server / Delphi / web
Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html
Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com
****************** mailto: ******************



FAUCHILLE Stéphan a écrit:
Désolé de revenir à la charge, j'ai essayé ta requete qui marche très bien,
sauf que j'ai dans ma table des cas particuliers

Je peux avoir

Id DateHeure Valeur(0=Arret;1=Marche)
1 18/11/2003 12:00:00 0
7 18/11/2003 12:30:00 0
2 18/11/2003 12:45:00 1
3 18/11/2003 14:55:00 0
4 18/11/2003 15:00:00 1
5 19/11/2003 12:00:00 0
6 19/11/2003 18:00:00 1

En cas de coupure de la base et de redémarrage, elle enregistre de nouveau
le point, donc je peux me retrouver avec 2 mêmes valeurs. Et là le cumul
n'est pas juste.

Autres soucis, est-ce que ça marche si je demande le temps de marche entre
deux valeurs qui ne sont pas des points enregistré, je m'explique :
- Si je fais ma requête entre 18/11/2003 12:15:30 et 18/11/2003 14:58:11

Désolée de te déranger ;-)

Merci

"Fred BROUARD" a écrit dans le message news:


bonjour

CREATE TABLE T_MOTEUR
(ID INT,
DATEHEURE DATETIME,
VALEUR BIT)

INSERT INTO T_MOTEUR VALUES (1, '18/11/2003 12:00:00', 0)
INSERT INTO T_MOTEUR VALUES (2, '18/11/2003 12:45:00', 1)
INSERT INTO T_MOTEUR VALUES (3, '18/11/2003 14:55:00', 0)
INSERT INTO T_MOTEUR VALUES (4, '18/11/2003 15:00:00', 1)
INSERT INTO T_MOTEUR VALUES (5, '19/11/2003 12:00:00', 0)
INSERT INTO T_MOTEUR VALUES (6, '19/11/2003 18:00:00', 1)

1ere phase : retrouver pour chaque ligne la suivante (début et fin) :

SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1

DHD DHF VALEUR
------------------------- ------------------------ ------
2003-11-18 12:00:00.000 2003-11-18 12:45:00.000 0
2003-11-18 12:45:00.000 2003-11-18 14:55:00.000 1
2003-11-18 14:55:00.000 2003-11-18 15:00:00.000 0
2003-11-18 15:00:00.000 2003-11-19 12:00:00.000 1
2003-11-19 12:00:00.000 2003-11-19 18:00:00.000 0
2003-11-19 18:00:00.000 NULL 1

Cette table peut maintenant être reprise dans la clause FROM d'une
nouvelle pour calcul :

SELECT DHF - DHD AS DUREE, VALEUR
FROM
(
SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1
) TT


DUREE VALEUR
------------------------------------------------------ ------
1900-01-01 00:45:00.000 0
1900-01-01 02:10:00.000 1
1900-01-01 00:05:00.000 0
1900-01-01 21:00:00.000 1
1900-01-01 06:00:00.000 0
NULL 1

Mais la réponse fait apparaitres des dates au liue de temps. Pour cela
transtypons en float :

SELECT CAST(DHF - DHD AS FLOAT) AS DUREE_JOUR, VALEUR
FROM
(
SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1
) TT

DUREE_JOUR VALEUR
----------------------------------------------------- ------
0.03125 0
9.0277777777777776E-2 1
3.4722222222222225E-3 0
0.875 1
0.25 0
NULL 1

Et pour obtenir des heures décimales :

SELECT CAST(DHF - DHD AS FLOAT) * 24 AS DUREE_H, VALEUR
FROM
(
SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1
) TT

DUREE_H VALEUR
----------------------------------------------------- ------
0.75 0
2.1666666666666665 1
8.3333333333333343E-2 0
21.0 1
6.0 0
NULL 1

En ajoutant cette fonction, nous avons les heures décimales converties
en HMS :

CREATE FUNCTION FN_CONVERT_HD_HMS (@HD FLOAT)
RETURNS VARCHAR(8)
AS

BEGIN

DECLARE @H INTEGER
DECLARE @M INTEGER
DECLARE @S INTEGER
DECLARE @RETVAL VARCHAR(8)

-- cas trivial
IF @HD IS NULL
RETURN NULL

-- récupération des heures, minutes, secondes
SET @H = FLOOR(@HD)
SET @HD = @HD - @H
SET @HD = @HD * 60
SET @M = FLOOR(@HD)
SET @HD = @HD - @M
SET @HD = @HD * 60
SET @S = FLOOR(@HD)

IF @H < 10
SET @RETVAL = '0'+CAST(@H AS CHAR(1))+':'
ELSE
SET @RETVAL = CAST(@H AS CHAR(2))+':'
IF @M < 10
SET @RETVAL = @RETVAL + '0' + CAST(@M AS CHAR(1))+':'
ELSE
SET @RETVAL = @RETVAL + CAST(@M AS CHAR(2))+':'
IF @S < 10
SET @RETVAL = @RETVAL + '0' + CAST(@S AS CHAR(1))
ELSE
SET @RETVAL = @RETVAL + CAST(@S AS CHAR(2))+':'

RETURN @RETVAL

END

La requête avec la fonction :

SELECT dbo.FN_CONVERT_HD_HMS (CAST(DHF - DHD AS FLOAT) * 24)
AS DUREE_HMS, VALEUR
FROM
(
SELECT DATEHEURE DHD, (SELECT MIN(DATEHEURE)
FROM T_MOTEUR T2
WHERE T2.DATEHEURE > T1.DATEHEURE
AND T2.VALEUR <> T1.VALEUR
GROUP BY T2.VALEUR) DHF, VALEUR
FROM T_MOTEUR T1
) TT

Le résultat :

DUREE_HMS VALEUR
---------- ------
00:45:00 0
02:09:59 1
00:05:00 0
21:00:00 1
06:00:00 0
NULL 1

etc...


Libre à toi après de faire un cumul (SUM) entre deux datetime (BETWEEN)
passées en paramètres...


A +



--
Frédéric BROUARD - expert SQL, spécialiste : SQL Server / Delphi / web
Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html
Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com
****************** mailto: ******************

FAUCHILLE Stéphan a écrit:

Bonjour à tous

J'ai une Table me permettant d'historiser les états de marche et d'arrêt
d'un moteur. A chaque fois qu'il se met en marche ou s'arrête, un





message

est enregistré.

Id DateHeure Valeur(0=Arret;1=Marche)
1 18/11/2003 12:00:00 0
2 18/11/2003 12:45:00 1
3 18/11/2003 14:55:00 0
4 18/11/2003 15:00:00 1
5 19/11/2003 12:00:00 0
6 19/11/2003 18:00:00 1

Voila la table avec des valeurs.

Maintenant je souhaite connaitre le temps de marche (ou d'arrêt) du





moteur

entre deux dates.

Par exemple le temps de marche du moteur entre le 18/11/2003 12:10:00 et
19/11/2003 11:00:00

Comment puis-je faire?

Si vous avez des idées.

D'avance merci et bon courage.

Stef











Avatar
FAUCHILLE Stéphan
Ca marche mais ça commence à faire gros. Je pensais cela faisable en une
seule requête. Mais bon.

Encore merci à toi.
Avatar
Fred BROUARD - SQLpro
En une seule requête oui, il suffit d'encapsuler les vues au sein des
from...

Mais les vues ont l'avantage d'une plus grande lisibilité et peuvent
être indexées...

A +

FAUCHILLE Stéphan a écrit :
Ca marche mais ça commence à faire gros. Je pensais cela faisable en une
seule requête. Mais bon.

Encore merci à toi.






Avatar
FAUCHILLE Stéphan
C'ai vrai, mais bon, c'est plus chiant de créer une vue et de la supprimer
après utilisation


"Fred BROUARD - SQLpro" a écrit dans le message
news: 3fbccde9$0$6974$
En une seule requête oui, il suffit d'encapsuler les vues au sein des
from...

Mais les vues ont l'avantage d'une plus grande lisibilité et peuvent
être indexées...

A +

FAUCHILLE Stéphan a écrit :
> Ca marche mais ça commence à faire gros. Je pensais cela faisable en une
> seule requête. Mais bon.
>
> Encore merci à toi.
>
>
>
>