Oracle SQL - 计算 sysdate 和 sysdate-7 天前在具有大量时间戳的(大)table 之间的数据差异(和 return 增长百分比)

OracleSQL - calculate difference (and return in %growth) in data between sysdate and sysdate-7 days ago in a (big) table with lots of timestamps

(OracleSQL) 我们有自己创建的应用程序,以 MB 为单位跟踪存储使用情况。我想要一个无需手动更改的查询(因为我们会将此查询集成到我们的应用程序中,它将自动定期 运行 此查询)可以计算自 sysdate 以来过去一周的存储差异。如果我们也能计算出这种增长百分比的差异,那就加分了!

我们使用的table已经自动收集存储信息。它每 X 分钟检查一次(老实说,我不确定多久一次,数据看起来相当随机,但至少每小时检查一次,而且经常比这更频繁)。

Client_Name Check_Timestamp Total_MB Used_MB Remaining_MB
Client1 03/28/2022 15:04:37 52280 20533 34747
Client1 03/28/2022 14:01:20 52280 20421 31859
Client1 03/21/2022 14:01:20 51090 20300 30790
Client1 03/21/2022 13:49:20 51090 20121 30969
Client2 03/28/2022 15:34:17 52280 20533 34747
Client2 03/28/2022 14:20:22 52280 20421 31859
Client2 03/21/2022 14:09:54 51090 20300 30790
Client2 03/21/2022 13:32:03 51090 20121 30969

到目前为止,我的尝试惨遭失败。

如有任何帮助,我们将不胜感激。

这里有一些可以帮助您入门的东西。此查询将查找每个客户端的最新条目(与 SYSDATE 相比),以及在 SYSDATE 之前恰好 7 天的最新条目。如果要与 TRUNC(SYSDATE) 进行比较,则可能需要将 SYSDATE 包装在 TRUNC 中。

您可以将其变成子查询并进行任何您需要的额外计算,例如增加 MB 和百分比。那部分是微不足道的;如果你不能自己添加,也许你一开始就不应该处理这些问题。

因为我是 运行 2022 年 4 月 20 日 10:26 我的时间,所以您的样本数据不相关。我改用这个(仅相关列):

create table storage_tracking
( client_name     varchar2(15)
, check_timestamp timestamp 
, used_mb number
);

alter session set nls_timestamp_format = 'mm/dd/yyyy hh24:mi:ss';

insert into storage_tracking
  select 'Client1', '04/20/2022 10:04:37',   20533 from dual union all
  select 'Client1', '04/19/2022 04:01:20',   20421 from dual union all
  select 'Client1', '04/13/2022 14:01:20',   20300 from dual union all
  select 'Client1', '04/13/2022 08:49:20',   20121 from dual union all
  select 'Client2', '04/20/2022 10:24:17',   20533 from dual union all
  select 'Client2', '04/20/2022 08:20:22',   20421 from dual union all
  select 'Client2', '04/14/2022 14:09:54',   20300 from dual union all
  select 'Client2', '04/12/2022 07:32:03',   20121 from dual
;

commit;

查询和输出:

select client_name,
       max(case when check_timestamp <= sysdate - 7 
                then check_timestamp end) as week_earlier,
       max(used_mb) keep (dense_rank last order by case 
                when check_timestamp <= sysdate - 7
                then check_timestamp end nulls first) as used_mb_week_earlier,
       max(case when check_timestamp <= sysdate
                then check_timestamp end) as now,
       max(used_mb) keep (dense_rank last order by case
                when check_timestamp <= sysdate
                then check_timestamp end nulls first) used_mb_now
from   storage_tracking
group  by client_name
;

CLIENT_NAME     WEEK_EARLIER        USED_MB_WEEK_EARLIER NOW                 USED_MB_NOW
--------------- ------------------- -------------------- ------------------- -----------
Client1         04/13/2022 08:49:20                20121 04/20/2022 10:04:37       20533
Client2         04/12/2022 07:32:03                20121 04/20/2022 10:24:17       20533

如果您只想要一天的值,并且想要最大总量和已用量以及最小剩余量,那么:

SELECT t.*,
       ROUND((total_mb / total_mb_last_week) * 100 - 100, 2) AS percent_total_growth,
       ROUND((used_mb / used_mb_last_week) * 100 - 100, 2) AS percent_used_growth,
       ROUND((remaining_mb / remaining_mb_last_week) * 100 - 100, 2) AS percent_remaining_growth
FROM   (
  SELECT client_name,
         TRUNC(Check_timestamp) AS check_day,
         MAX(total_mb) AS total_mb,
         MAX(used_mb) AS used_mb,
         MIN(remaining_mb) AS remaining_mb,
         MAX(MAX(total_mb)) OVER (
           PARTITION BY Client_Name
           ORDER BY TRUNC(Check_Timestamp)
           RANGE BETWEEN INTERVAL '7' DAY PRECEDING AND INTERVAL '7' DAY PRECEDING
         ) AS total_mb_last_week,
         MAX(MAX(used_mb)) OVER (
           PARTITION BY Client_Name
           ORDER BY TRUNC(Check_Timestamp)
           RANGE BETWEEN INTERVAL '7' DAY PRECEDING AND INTERVAL '7' DAY PRECEDING
         ) AS used_mb_last_week,
         MAX(MIN(remaining_mb)) OVER (
           PARTITION BY Client_Name
           ORDER BY TRUNC(Check_Timestamp)
           RANGE BETWEEN INTERVAL '7' DAY PRECEDING AND INTERVAL '7' DAY PRECEDING
         ) AS remaining_mb_last_week
  FROM   table_name
  GROUP BY client_name, TRUNC(Check_Timestamp)
) t
WHERE check_day = DATE '2022-03-28';

Will,对于您的示例数据:

CREATE TABLE table_name (Client_Name, Check_Timestamp, Total_MB, Used_MB, Remaining_MB) AS
SELECT 'Client1', DATE '2022-03-28' + INTERVAL '15:04:37' HOUR TO SECOND, 52280, 20533, 34747 FROM DUAL UNION ALL
SELECT 'Client1', DATE '2022-03-28' + INTERVAL '14:01:20' HOUR TO SECOND, 52280, 20421, 31859 FROM DUAL UNION ALL
SELECT 'Client1', DATE '2022-03-21' + INTERVAL '14:01:20' HOUR TO SECOND, 51090, 20300, 30790 FROM DUAL UNION ALL
SELECT 'Client1', DATE '2022-03-21' + INTERVAL '13:49:20' HOUR TO SECOND, 51090, 20121, 30969 FROM DUAL UNION ALL
SELECT 'Client2', DATE '2022-03-28' + INTERVAL '15:34:17' HOUR TO SECOND, 52280, 20533, 34747 FROM DUAL UNION ALL
SELECT 'Client2', DATE '2022-03-28' + INTERVAL '14:20:22' HOUR TO SECOND, 52280, 20421, 31859 FROM DUAL UNION ALL
SELECT 'Client2', DATE '2022-03-21' + INTERVAL '14:09:54' HOUR TO SECOND, 51090, 20300, 30790 FROM DUAL UNION ALL
SELECT 'Client2', DATE '2022-03-21' + INTERVAL '13:32:03' HOUR TO SECOND, 51090, 20121, 30969 FROM DUAL;

输出:

CLIENT_NAME CHECK_DAY TOTAL_MB USED_MB REMAINING_MB TOTAL_MB_LAST_WEEK USED_MB_LAST_WEEK REMAINING_MB_LAST_WEEK PERCENT_TOTAL_GROWTH PERCENT_USED_GROWTH PERCENT_REMAINING_GROWTH
Client1 28-MAR-22 52280 20533 31859 51090 20300 30790 2.33 1.15 3.47
Client2 28-MAR-22 52280 20533 31859 51090 20300 30790 2.33 1.15 3.47

如果您想要当天的值(您尚未提供数据),请将最后一行更改为:

WHERE  check_day = TRUNC(SYSDATE);

或者,如果您想获取数据库中所有日期的值,请删除该 WHERE 子句。

db<>fiddle here