Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle和MS SQL查询根据日期和时间从一行中获取多行_Sql_Sql Server_Oracle_Tsql - Fatal编程技术网

Oracle和MS SQL查询根据日期和时间从一行中获取多行

Oracle和MS SQL查询根据日期和时间从一行中获取多行,sql,sql-server,oracle,tsql,Sql,Sql Server,Oracle,Tsql,您好,我收到了Oracle查询,返回: 我需要得到所有数据的结果。第一行的示例: SensorKey StartTime EndTime 45 2012.10.17 08:31 2012.10.17 10:21 与其他行类似,以此类推: TimeKey Hour SensorKey Duration StartTime EndTime 20121017 8 45 29 20

您好,我收到了Oracle查询,返回:

我需要得到所有数据的结果。第一行的示例:

   SensorKey    StartTime          EndTime
    45         2012.10.17 08:31 2012.10.17 10:21
与其他行类似,以此类推:

TimeKey    Hour  SensorKey  Duration    StartTime   EndTime
20121017    8         45         29     2012.10.17 08:31    2012.10.17 10:21
20121017    9         45         60     2012.10.17 08:31    2012.10.17 10:21
20121017    10        45         21     2012.10.17 08:31    2012.10.17 10:21
规则:

  • 将一行复制如此多的时间重叠,例如第一行重叠8、9、10小时

  • Timekey
    =格式为
    YYYYMMDD

    Hour
    =从
    StartTime
    开始的小时,格式为
    H
    24H

    持续时间
    以分钟为单位的小时持续时间

  • 如果一小时内有几行,则必须对它们进行分组,例如前两行:


    对于Oracle来说,一种方法是Model子句(当我们组成行时,Model子句可以为我们做到这一点)

    有几件事。您似乎只需要精确到分钟的数据,因此使用日期与时间戳是有意义的。其次,我要避免在oracle中的表中使用区分大小写的名称(在下面的查询中,我将您的数据化名为非区分大小写,以便更容易编码:)

    一些注意事项: 首先,我计算了每行所需的小时数

    SQL> select rownum id, "SensorKey" s_key, cast("StartTime" as date) s_time, cast("EndTime" as date) e_time,
      2         ((trunc(cast("EndTime" as date) , 'hh24') -trunc(cast("StartTime" as date), 'hh24')) *24)+1 hours
      3    from table1;
    
            ID      S_KEY S_TIME            E_TIME                 HOURS
    ---------- ---------- ----------------- ----------------- ----------
             1         45 17-oct-2012 08:31 17-oct-2012 10:21          3
    
    这个“小时”列将驱动model子句,告诉它每个源行要生成多少行。rownum ID仅用于唯一键(因为其他数据似乎不能保证唯一性)

    我按ID分区

    model partition by (id as key)
    
    这意味着我们将每一行作为一个独立的处理位

    在度量中,我们列出了要处理的字段(计算或只是输出)

    cast()
    列只是不在原始集合中的列,但我们将在运行时进行计算。
    duration
    将保存分钟,
    小时
    将显示小时数,
    将保存当前小时所在的时段

    规则是我们所有逻辑的起点。因此:

    rules (block_start[for f from 0 to hours[0]-1 increment 1] = trunc(s_time[0] + (cv(f)/24), 'hh24'),
    
    “对于从0到小时[0]-1增量1的f”
    表示我们正在基于
    hours
    列生成行(第一行为3)

    第一排的区块开始时间将设置为
    2012年10月17日08:00
    ,区块结束时间将设置为
    09:00
    (第二排的区块开始时间将增加一小时,以此类推)

    s_key[any] = s_key[0],
    s_time[any] = s_time[0],
    e_time[any] = e_time[0],
    
    以上三项只是按原样复制到输出集中。ANY关键字意味着匹配所有行(我们可以在这里放置“for f…”逻辑,但ANY更整洁

    使用case语句计算持续时间

     case 
      when cv(f) = 0
      then (least(block_end[cv(f)],e_time[0]) - s_time[0]) * 24*60
      when cv(f) =  hours[0]-1
      then (e_time[0] - block_start[cv(f)] ) * 24*60
      else (block_end[cv(f)] - block_start[cv(f)] ) * 24*60
    end
    
    i、 e.
    cv(f)=0
    表示第一个输出行(
    cv
    bie)函数,用于访问
    f
    变量的“当前值”。 所以第一行,我们取块结束(
    17-oct-2012 09:00
    )-开始时间(
    17-oct-2012 08:31
    ),以分钟(29分钟)为单位。 对于结束行,我们采用结束时间(
    2012年10月17日10:21
    )-块开始(
    2012年10月17日10:00
    )=21分钟 对于中间的所有行,我们只需从块开始处扣除块结束(即60分钟)

    这将为我们提供如下输出:

    TimeKey        Hour  SensorKey   Duration StartTime         EndTime
    -------- ---------- ---------- ---------- ----------------- -----------------
    20121017          8         45         29 17-oct-2012 08:31 17-oct-2012 10:21
    20121017          9         45         60 17-oct-2012 08:31 17-oct-2012 10:21
    20121017         10         45         21 17-oct-2012 08:31 17-oct-2012 10:21
    20121017         10         45         25 17-oct-2012 10:26 17-oct-2012 10:51
    ...etc..
    
    但是你说把“10”行分组,所以现在只需分组即可完成:

    select to_char(block_start, 'yyyymmdd') "TimeKey",
           thehour "Hour", s_key "SensorKey", 
           sum(duration) "Duration", min(s_time) "StartTime", max(e_time) "EndTime"
      from (..our model query...)
      group by block_start, thehour, s_key;
    

    +1可能它在正常情况下可以工作,但我使用SSIS时使用了一些“有趣的”Oracle Odbc,所以这太复杂了(我认为这会容易得多)。我现在决定等待一些ms sql查询…@Justin ok。你可以将其放在视图中,这将从Odbc层隐藏主sql。还有一些其他方法可以做到这一点(可能是流水线函数,笛卡尔连接[dual connect by trick]生成最大行数,然后过滤掉等,递归子查询[11g])。
    s_key[any] = s_key[0],
    s_time[any] = s_time[0],
    e_time[any] = e_time[0],
    
     case 
      when cv(f) = 0
      then (least(block_end[cv(f)],e_time[0]) - s_time[0]) * 24*60
      when cv(f) =  hours[0]-1
      then (e_time[0] - block_start[cv(f)] ) * 24*60
      else (block_end[cv(f)] - block_start[cv(f)] ) * 24*60
    end
    
    TimeKey        Hour  SensorKey   Duration StartTime         EndTime
    -------- ---------- ---------- ---------- ----------------- -----------------
    20121017          8         45         29 17-oct-2012 08:31 17-oct-2012 10:21
    20121017          9         45         60 17-oct-2012 08:31 17-oct-2012 10:21
    20121017         10         45         21 17-oct-2012 08:31 17-oct-2012 10:21
    20121017         10         45         25 17-oct-2012 10:26 17-oct-2012 10:51
    ...etc..
    
    select to_char(block_start, 'yyyymmdd') "TimeKey",
           thehour "Hour", s_key "SensorKey", 
           sum(duration) "Duration", min(s_time) "StartTime", max(e_time) "EndTime"
      from (..our model query...)
      group by block_start, thehour, s_key;