我有一个包含下一列的表
MSG_ID NOT NULL NUMBER(10)
CREATION_DATE DATE
PORT VARCHAR2(50)
MESSAGE VARCHAR2(1024)
IP_ADDRESS VARCHAR2(50)
PARSED NUMBER(1)
PARSED_ON DATE
解析时间为parsed_on - creation_date。
我想知道是否有可能在1个单一查询中提取每小时需要更长时间解析的消息,获得HOUR,PORT,MSG_ID MINUTES ......我在这里被阻止
select TO_CHAR(CREATION_DATE, 'HH24') || ':mm' HOUR, PORT, MSG_ID, ROUND(MAX(parsed_on - creation_date)) * 24*60 MINUTES
from T_INCOME_CALLS
where TO_CHAR(CREATION_DATE, 'dd/mm/yyyy') = TO_CHAR(SYSDATE, 'dd/mm/yyyy')
group by TO_CHAR(CREATION_DATE, 'HH24'), PORT, MSG_ID
order by TO_CHAR(CREATION_DATE, 'HH24') ;
答案 0 :(得分:1)
您可以使用窗口函数row_number来查找每小时分析时间最长的行,如下所示:
select *
from (
select to_number(to_char(creation_date, 'HH24')) as hour,
port,
msg_id,
round(parsed_on - creation_date) * 24 * 60 as parse_time,
row_number() over (
partition by to_char(creation_date, 'HH24'), port, msg_id
order by (parsed_on - creation_date) desc nulls last
) as rn
from t_income_calls t
where creation_date between trunc(sysdate)
and trunc(sysdate + 1) - interval '1' second
) t
where rn = 1;
另外,请注意过滤器。我在creation_date上使用了日期范围而不是to_char。在creation_date上使用to_char会禁止在creation_date上使用索引(如果存在)。
答案 1 :(得分:1)
我认为需要的是每小时花费大部分时间的项目,用于IP_ADDRESS和PORT的分组,这与您的原始查询不同。我也假设MSG_ID是唯一的。
如果您希望每个记录小时只有1行,那么请使用row_number()
,如果您想要绑定值,请在下面的查询中替换dense_rank()
。 create_on日期已被用作排序烧杯。
SELECT
TO_CHAR(CREATION_DATE, 'HH24') || ':mm' HOUR
, PORT, MSG_ID
, ROUND(parsed_on - creation_date) * 24*60 MINUTES
FROM (
SELECT
T_INCOME_CALLS.*
, ROW_NUMBER() OVER(PARTITION BY IP_ADDRESS, port, TO_CHAR(CREATION_DATE, 'HH24')
ORDER BY (parsed_on - creation_date) desc, CREATION_DATE) AS rn
FROM T_INCOME_CALLS
WHERE CREATION_DATE >= TRUNC(SYSDATE) AND CREATION_DATE < TRUNC(SYSDATE) + 1
)
WHERE rn = 1
请避免将日期转换为where子句的字符串,这样效率不高。而是保持created_on不变,并修改标准以适应允许访问过滤索引的数据。
答案 2 :(得分:1)
使用FIRST函数时,您也可以在没有子查询的情况下获取它:
SELECT TO_CHAR(CREATION_DATE, 'HH24') || ':mm' HOUR, PORT, MSG_ID,
MAX(MESSAGE) KEEP (DENSE_RANK FIRST ORDER BY (parsed_on - creation_date) desc, CREATION_DATE)
FROM T_INCOME_CALLS
WHERE CREATION_DATE >= TRUNC(SYSDATE) AND CREATION_DATE < TRUNC(SYSDATE) + 1
GROUP BY TO_CHAR(CREATION_DATE, 'HH24'), PORT, MSG_ID
ORDER BY TO_CHAR(CREATION_DATE, 'HH24');