Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.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
Sql 显示特定时间范围的值_Sql_Database_Oracle_Average_Self Join - Fatal编程技术网

Sql 显示特定时间范围的值

Sql 显示特定时间范围的值,sql,database,oracle,average,self-join,Sql,Database,Oracle,Average,Self Join,当我在下面运行时,请选择: select name, time, value from table1 where name like '%Z' or '%V' 我得到的结果是: 我需要做两件事: 每小时将运行一次查询,因此如果我们有12.00.00PM范围,则应在11和12>PM之间,如果是02.00.00AM范围,则应为01和02>AM 2第二件事是将以“%Z”或“%V”结尾的名称的avgvalue显示为一行,但显示为两列 以下是在下午12:00.00运行查询时理想结果的示例: 你要求的是三

当我在下面运行时,请选择:

select name, time, value from table1 where name like '%Z' or '%V'
我得到的结果是:

我需要做两件事:

每小时将运行一次查询,因此如果我们有12.00.00PM范围,则应在11和12>PM之间,如果是02.00.00AM范围,则应为01和02>AM

2第二件事是将以“%Z”或“%V”结尾的名称的avgvalue显示为一行,但显示为两列

以下是在下午12:00.00运行查询时理想结果的示例:


你要求的是三件事,可以看作是三个步骤。获取时间窗口是相当简单的,并且由于列是时间戳而不是日期,所以稍微复杂一些。你暗示这将在一小时内运行,但有可能是稍晚一点-可能是一两秒钟所以考虑到这一点可能更安全。您可以使用将日期值修改为所需的精度,以便只查看当前小时,将截断为HH[24]。然后可以将其返回到时间戳。您可以使用查找该时间之前的小时:

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设置;用于将日期时间值的最终格式设置为字符串

请注意,截断的结果现在是该输出中的日期a,因此我将其转换回时间戳B。您需要的范围基本上是时间>=a和时间 对于使用systimestamp或sysdate的示例数据,不会找到任何东西,因此我将使用在CTE中生成的假固定时间来分离其余数据。我现在在CTE中使用的是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
可能还需要另一个步骤;在您的样本输出中,您包含了一个平均原始值的列表,但没有确认您是否真的想要这些值,或者它们只是为了显示如何计算平均值,以帮助我们了解您需要做什么。如果您确实希望包含,可以在旋转前使用listagg和串联来构建“平均”字符串:

    '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
正如我前面所说的,我只使用假日期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));

查看分组方式!你真的想显示平均值列表,还是仅仅显示平均值本身?时间范围部分相当直截了当;如果您也想要列表,那么聚合只是稍微复杂一点。另外,源数据(如DDL/DML)也会有帮助。顺便问一下,您的查询是否实际执行?!?晚上11点到12点>之间是什么意思?特别是12点>部分?“中间”是包容性的。你想要>=11和<12,还是其他什么?@Alex你是对的,应该是>=11,我得到了错误:ORA-30089:丢失或无效……。当我只运行一个select时,我得到了相同的错误可能你必须在查询中使用时间列上的日期函数:我添加了:……间隔“1”小时,然后一个查询工作,但整个语句都有错误:ORA-00907:缺少右括号谢谢你的解释,但我无法执行任何alter会话:/@4est-alter会话只是控制在我的客户端中默认情况下日期和时间戳的显示方式,这主要是为了显示这两种数据类型之间的区别。无论如何,你不应该依赖NLS设置;对于您的最终输出,如果它没有被其他进程使用,您应该使用字符来格式化时间戳值。@alex:应该用什么来代替从dual中选择时间戳“2017-02-10 13:01:07”进入我的组织查询?@4est-您根本不需要假日期CTE。我在问题中说,在我现在使用的地方,在真正的查询中使用sysdate或systimestamp。您可以使用CTE来避免多次trunc/cast值,但这不是演示所必需的-您可以根据需要进行扩展。现在回想起来,使用now可能会让人困惑,因为这是其他系统中的一个函数……您能输入正确的查询吗?这对我来说是进口货,我不想做任何米亚斯塔克
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
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));