如何减少一行到开始时间和结束时间到多天花费数小时的行

时间:2019-05-03 06:05:57

标签: sql oracle

问题:

如何将一行剪切为开始时间,将结束时间剪切为多个时间,花费小时行

表格数据和DDL:

starttime           , endtime
2019/05/03 08:00:00 , 2019/05/05 12:00:00
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');

预期结果:

Date        , SpendHour
2019/05/03 , 16
2019/05/04 , 24
2019/05/05 , 12
Online Demo Link | DB Fiddle

3 个答案:

答案 0 :(得分:4)

您可以结合使用connect by level <=语法和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;

Demo

答案 1 :(得分:2)

即使肯定会有更优雅的解决方案。这将带来预期的结果:

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

结果:

 TIMES                 DIFF
 03/05/2019 08:00:00   16
 04/05/2019            24
 05/05/2019 12:00:00   12

答案 2 :(得分:2)

试试这个兄弟, 您可以将最终选择更改为“ SELECT * FROM tbl”,以查看其运行方式。

;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