Oracle和MS SQL查询根据日期和时间从一行中获取多行
您好,我收到了Oracle查询,返回: 我需要得到所有数据的结果。第一行的示例: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
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
规则:
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;