簡體   English   中英

如何選擇具有最大值的列和分組依據的行

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM