Comment couper une ligne à l'heure de début et à l'heure de fin en plusieurs lignes d'heures de dépenses par jour
Date , SpendHour 2019/05/03 , 16 2019/05/04 , 24 2019/05/05 , 12
CREATE TABLE T ("starttime" timestamp, "endtime" timestamp); INSERT INTO T ("starttime", "endtime") VALUES ('03-May-2019 08:00:00 AM', '05-May-2019 12:00:00 PM');
starttime , endtime 2019/05/03 08:00:00 , 2019/05/05 12:00:00Lien de démonstration en ligne | DB Fiddle
3 Réponses :
même s'il y aura sûrement des solutions plus élégantes. Cela donnera le résultat souhaité:
TIMES DIFF 03/05/2019 08:00:00 16 04/05/2019 24 05/05/2019 12:00:00 12
Résultat:
WITH cte ( starttime ) AS ( SELECT CAST(TO_DATE('03.05.2019:08:00:00','dd.mm.yyyy:hh24:mi:ss') AS DATE) cte_date FROM dual UNION ALL SELECT CAST( (starttime + 1) AS DATE) starttime FROM cte WHERE trunc(starttime) + 1 <= TO_DATE('05.05.2019:12:00:00','dd.mm.yyyy:hh24:mi:ss') ),starttime AS ( SELECT TO_DATE('03.05.2019:08:00:00','dd.mm.yyyy:hh24:mi:ss') AS starttime FROM dual ),endtime AS ( SELECT TO_DATE('05.05.2019:12:00:00','dd.mm.yyyy:hh24:mi:ss') AS endtime FROM dual ) SELECT a.*, CASE WHEN TO_CHAR( (trunc(times + 1) ),'hh24') - TO_CHAR(times,'hh24') = 0 THEN -24 *-1 ELSE ( 24 - ( TO_CHAR( (trunc(times + 1) ),'hh24') - TO_CHAR(times,'hh24') ) *-1 ) END diff FROM( SELECT CASE WHEN TO_CHAR(starttime,'yyyy-mm-dd') = (SELECT TO_CHAR(endtime,'yyyy-mm-dd') FROM endtime) THEN ( SELECT endtime FROM endtime ) WHEN TO_CHAR(starttime,'yyyy-mm-dd') = (SELECT TO_CHAR(starttime,'yyyy-mm-dd') FROM starttime) THEN ( SELECT starttime FROM starttime ) ELSE trunc(starttime) END times FROM cte a ) a
Vous pouvez utiliser la syntaxe connect by level combinée avec des instructions
case..when
select trunc(t.starttime+level-1) as "Date",
case
when trunc(t.starttime+level-1) = trunc(t.starttime) then
extract(hour from trunc(t.starttime+level)
-greatest(t.starttime,trunc(t.starttime+level-1)))
when trunc(t.starttime+level-1) = trunc(t.endtime) then
extract(hour from t.endtime-trunc(t.endtime))
else
24
end as "Spend hour"
from t
connect by level <= extract(day from t.endtime - t.starttime)+1;
Essayez ce frère, vous pouvez changer la sélection finale en "SELECT * FROM tbl" pour voir comment elle s'exécute.
;WITH tbl AS ( SELECT "starttime" AS Date0, DATEADD(HH,24-DATEPART(HH,"starttime"),"starttime") AS "endtime0", DATEDIFF(HH,"starttime",DATEADD(HH,24-DATEPART(HH,"starttime"),"starttime")) AS SPENTTIME, "endtime" FROM T UNION ALL SELECT Date0+1,"endtime0"+1, CASE WHEN "endtime0"+1>"endtime" THEN DATEDIFF(HH,Date0+1,DATEADD(HH,24-DATEPART(HH,"endtime"),Date0+1)) ELSE DATEDIFF(HH,Date0+1,DATEADD(HH,24,Date0+1)) END AS SPENTTIME , "endtime" FROM tbl WHERE Date0+1<"endtime" ) SELECT CONVERT(NVARCHAR(20),Date0,111) AS Date,SPENTTIME FROM tbl
y a-t-il une colonne id dans votre table qui peut identifier des combinaisons uniques de date de début et de date de fin?
oui chaque ligne a un identifiant de pk