显示特定时间范围的值
Display values for specific time-frame
当我运行低于select时:
select name, time, value from table1 where name like '%Z' or '%V'
我得到了结果:
我需要做两件事:
1) 查询将每小时 运行,所以如果我们有 12.00.00PM,范围应该在(11 点和 12> PM 之间,如果是 02.00。 00AM 范围将是(01 和 02> AM
2) 第二件事是将以 '%Z' 或 '%V' 结尾的名称的 avg(value) 显示到 一行, 但分为 两列
以下是理想结果的示例,查询时间为 运行 下午 12.00.00:
select T1.Z, T1.V from (
(select avg(values) from table1 where name like '%Z' and time between sysdate and sysdate - interval '1' group by INSTR(name,'Z')) Z,
(select avg(values) from table1 where name like '%V' and time between sysdate and sysdate - interval '1' group by INSTR(name,'V')) V ) T1
你要求的是三件事,可以认为是三步。获取时间 window 非常简单,只是因为您的列是时间戳而不是日期而稍微复杂一些。您暗示这将在整点 运行,但它可能会稍晚一些 - 也许一两秒? - 所以考虑到这一点可能更安全。您可以使用 the trunc()
function to modify a date value to the required precision, so to only look at the current hour you would truncate to HH[24]. You can then cast that back to a timestamp. And you can use interval arithmetic 查找之前的小时:
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS';
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS.FF3';
alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS.FF3 TZR';
select systimestamp,
trunc(systimestamp, 'HH24') as a,
cast(trunc(systimestamp, 'HH24') as timestamp) as b,
cast(trunc(systimestamp, 'HH24') as timestamp) - interval '1' hour as c
from dual;
SYSTIMESTAMP A B C
------------------------------ ------------------- ----------------------- -----------------------
2017-03-01 09:25:39.342 +00:00 2017-03-01 09:00:00 2017-03-01 09:00:00.000 2017-03-01 08:00:00.000
alter session
命令只是控制不同数据类型的显示方式,以供比较。 (不要依赖实际代码中的 NLS 设置;使用 to_char()
将日期时间值最终格式化为字符串)。
请注意,t运行cation 的结果现在是一个日期(该输出中的 A),因此我将其转换回时间戳 (B)。你想要的范围本质上是 time >= A and time < B
。您可以使用 sysdate
而不是 systimestamp
作为 trunc()
.
的输入
对于您使用 systimestamp
或 sysdate
的样本数据将找不到任何东西,因此我将使用一个假的固定时间来处理其余部分,在 CTE 中生成以进行分离。在我使用 CTE 中的 now
的地方,您可以使用 systimestamp 或 sysdate。
第二部分是获取该时间段内每个名称的平均值。这是简单的聚合:
with fake_time(now) as (
select timestamp '2017-02-10 13:01:07' from dual
)
select name,
avg(value) as avg_value,
cast(trunc(now, 'HH24') as timestamp) as time
from fake_time
join table1 on time >= cast(trunc(now, 'HH24') as timestamp) - interval '1' hour
and time < cast(trunc(now, 'HH24') as timestamp)
group by name, now;
NAME AVG_VALUE TIME
------- ---------- -----------------------
QWER1_Z 20 2017-02-10 13:00:00.000
QWER1_V 35 2017-02-10 13:00:00.000
TEST1_Z 15 2017-02-10 13:00:00.000
TEST1_V 10 2017-02-10 13:00:00.000
为了选择您想要的行,我将假时间设为 13:00 而不是 12:00。您显示的 TEST1_V
的平均值也是错误的。
下一阶段,它将把这些转换成你想要的格式,作为一行。为此,您可以将根(即 TEST1
或 QWER1
)和字母(Z 或 V)添加为结果集中的额外列,然后将其用作 [=32= 的子查询] - 这需要 11g 或更高:
with fake_time(now) as (
select timestamp '2017-02-10 13:01:07' from dual
)
select z_name, z_value, v_name, v_value, time
from (
select substr(name, 1, length(name) - 2) as root,
substr(name, -1) as zv,
name,
avg(value) as avg_value,
cast(trunc(now, 'HH24') as timestamp) as time
from fake_time
join table1 on time >= cast(trunc(now, 'HH24') as timestamp) - interval '1' hour
and time < cast(trunc(now, 'HH24') as timestamp)
group by substr(name, 1, length(name) - 2), name, now
)
pivot (max(name) as name, max(avg_value) as value for (zv) in ('Z' as z, 'V' as v));
Z_NAME Z_VALUE V_NAME V_VALUE TIME
------- ---------- ------- ---------- -----------------------
TEST1_Z 15 TEST1_V 10 2017-02-10 13:00:00.000
QWER1_Z 20 QWER1_V 35 2017-02-10 13:00:00.000
可能还需要一个步骤;在您的示例输出中,您包含了一个原始值的列表,这些值是平均的,但没有确认您是否真的想要这些值,或者它们是否只是为了显示平均值是如何计算的,以帮助我们理解您需要做什么。如果你真的想要包括你可以使用 listagg()
和连接在旋转之前构建 'average' 字符串:
'avg(' || listagg(value, ',') within group (order by value) || ') = ' || avg(value)
as avg_value,
得到
Z_NAME Z_VALUE V_NAME V_VALUE TIME
------- -------------------- ------- -------------------- -----------------------
TEST1_Z avg(10,20) = 15 TEST1_V avg(10) = 10 2017-02-10 13:00:00.000
QWER1_Z avg(20) = 20 QWER1_V avg(30,40) = 35 2017-02-10 13:00:00.000
正如我之前所说,我只使用 fake_date
CTE 来获取与您的样本数据相匹配的日期。您的真实查询将更像是:
select z_name, z_value, v_name, v_value, time
from (
select substr(name, 1, length(name) - 2) as root,
substr(name, -1) as zv,
name,
avg(value) as avg_value,
cast(trunc(sysdate, 'HH24') as timestamp) as time
from table1
where time >= cast(trunc(sysdate, 'HH24') as timestamp) - interval '1' hour
and time < cast(trunc(sysdate, 'HH24') as timestamp)
group by substr(name, 1, length(name) - 2), name
)
pivot (max(name) as name, max(avg_value) as value for (zv) in ('Z' as z, 'V' as v));
当我运行低于select时:
select name, time, value from table1 where name like '%Z' or '%V'
我得到了结果:
我需要做两件事:
1) 查询将每小时 运行,所以如果我们有 12.00.00PM,范围应该在(11 点和 12> PM 之间,如果是 02.00。 00AM 范围将是(01 和 02> AM
2) 第二件事是将以 '%Z' 或 '%V' 结尾的名称的 avg(value) 显示到 一行, 但分为 两列
以下是理想结果的示例,查询时间为 运行 下午 12.00.00:
select T1.Z, T1.V from (
(select avg(values) from table1 where name like '%Z' and time between sysdate and sysdate - interval '1' group by INSTR(name,'Z')) Z,
(select avg(values) from table1 where name like '%V' and time between sysdate and sysdate - interval '1' group by INSTR(name,'V')) V ) T1
你要求的是三件事,可以认为是三步。获取时间 window 非常简单,只是因为您的列是时间戳而不是日期而稍微复杂一些。您暗示这将在整点 运行,但它可能会稍晚一些 - 也许一两秒? - 所以考虑到这一点可能更安全。您可以使用 the trunc()
function to modify a date value to the required precision, so to only look at the current hour you would truncate to HH[24]. You can then cast that back to a timestamp. And you can use interval arithmetic 查找之前的小时:
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS';
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS.FF3';
alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS.FF3 TZR';
select systimestamp,
trunc(systimestamp, 'HH24') as a,
cast(trunc(systimestamp, 'HH24') as timestamp) as b,
cast(trunc(systimestamp, 'HH24') as timestamp) - interval '1' hour as c
from dual;
SYSTIMESTAMP A B C
------------------------------ ------------------- ----------------------- -----------------------
2017-03-01 09:25:39.342 +00:00 2017-03-01 09:00:00 2017-03-01 09:00:00.000 2017-03-01 08:00:00.000
alter session
命令只是控制不同数据类型的显示方式,以供比较。 (不要依赖实际代码中的 NLS 设置;使用 to_char()
将日期时间值最终格式化为字符串)。
请注意,t运行cation 的结果现在是一个日期(该输出中的 A),因此我将其转换回时间戳 (B)。你想要的范围本质上是 time >= A and time < B
。您可以使用 sysdate
而不是 systimestamp
作为 trunc()
.
对于您使用 systimestamp
或 sysdate
的样本数据将找不到任何东西,因此我将使用一个假的固定时间来处理其余部分,在 CTE 中生成以进行分离。在我使用 CTE 中的 now
的地方,您可以使用 systimestamp 或 sysdate。
第二部分是获取该时间段内每个名称的平均值。这是简单的聚合:
with fake_time(now) as (
select timestamp '2017-02-10 13:01:07' from dual
)
select name,
avg(value) as avg_value,
cast(trunc(now, 'HH24') as timestamp) as time
from fake_time
join table1 on time >= cast(trunc(now, 'HH24') as timestamp) - interval '1' hour
and time < cast(trunc(now, 'HH24') as timestamp)
group by name, now;
NAME AVG_VALUE TIME
------- ---------- -----------------------
QWER1_Z 20 2017-02-10 13:00:00.000
QWER1_V 35 2017-02-10 13:00:00.000
TEST1_Z 15 2017-02-10 13:00:00.000
TEST1_V 10 2017-02-10 13:00:00.000
为了选择您想要的行,我将假时间设为 13:00 而不是 12:00。您显示的 TEST1_V
的平均值也是错误的。
下一阶段,它将把这些转换成你想要的格式,作为一行。为此,您可以将根(即 TEST1
或 QWER1
)和字母(Z 或 V)添加为结果集中的额外列,然后将其用作 [=32= 的子查询] - 这需要 11g 或更高:
with fake_time(now) as (
select timestamp '2017-02-10 13:01:07' from dual
)
select z_name, z_value, v_name, v_value, time
from (
select substr(name, 1, length(name) - 2) as root,
substr(name, -1) as zv,
name,
avg(value) as avg_value,
cast(trunc(now, 'HH24') as timestamp) as time
from fake_time
join table1 on time >= cast(trunc(now, 'HH24') as timestamp) - interval '1' hour
and time < cast(trunc(now, 'HH24') as timestamp)
group by substr(name, 1, length(name) - 2), name, now
)
pivot (max(name) as name, max(avg_value) as value for (zv) in ('Z' as z, 'V' as v));
Z_NAME Z_VALUE V_NAME V_VALUE TIME
------- ---------- ------- ---------- -----------------------
TEST1_Z 15 TEST1_V 10 2017-02-10 13:00:00.000
QWER1_Z 20 QWER1_V 35 2017-02-10 13:00:00.000
可能还需要一个步骤;在您的示例输出中,您包含了一个原始值的列表,这些值是平均的,但没有确认您是否真的想要这些值,或者它们是否只是为了显示平均值是如何计算的,以帮助我们理解您需要做什么。如果你真的想要包括你可以使用 listagg()
和连接在旋转之前构建 'average' 字符串:
'avg(' || listagg(value, ',') within group (order by value) || ') = ' || avg(value)
as avg_value,
得到
Z_NAME Z_VALUE V_NAME V_VALUE TIME
------- -------------------- ------- -------------------- -----------------------
TEST1_Z avg(10,20) = 15 TEST1_V avg(10) = 10 2017-02-10 13:00:00.000
QWER1_Z avg(20) = 20 QWER1_V avg(30,40) = 35 2017-02-10 13:00:00.000
正如我之前所说,我只使用 fake_date
CTE 来获取与您的样本数据相匹配的日期。您的真实查询将更像是:
select z_name, z_value, v_name, v_value, time
from (
select substr(name, 1, length(name) - 2) as root,
substr(name, -1) as zv,
name,
avg(value) as avg_value,
cast(trunc(sysdate, 'HH24') as timestamp) as time
from table1
where time >= cast(trunc(sysdate, 'HH24') as timestamp) - interval '1' hour
and time < cast(trunc(sysdate, 'HH24') as timestamp)
group by substr(name, 1, length(name) - 2), name
)
pivot (max(name) as name, max(avg_value) as value for (zv) in ('Z' as z, 'V' as v));