![](/img/trans.png)
[英]SQL - How to select a row having a column with max value (+ group by)
[英]How to select a row having a column with max value with a group by
我有一張桌子,后面有幾列
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。
我想知道是否有可能每小時對消息進行一次較長時間的解析,從而獲取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') ;
您可以使用窗口函數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上使用索引(如果存在)。
我假設需要將每小時花費最多時間的項目用於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不變,並修改標准以適合該數據,以允許訪問索引以進行過濾。
使用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');
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.