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
(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