如何使用 Oracle sql 汇总每月的数据库和以前的数据
how to aggregate data base per month and previous data with oracle sql
假设我们有一个简单的 table“示例”,如下所示:
id time
1 2-2-20
2 3-1-20
3 15-2-20
4 20-3-20
我想按包含上个月数据的每个月计算行数,并获得每个月的平均数据(按指定月份的行数划分):
month rows_num avg_per_day
1-20 1 1/31
2-20 2+1 2/29
3-20 2+1+1 1/31
我正在考虑是否可以像这样使用 sql 但不会包含上个月的数据并且不知道如何处理平均值:
select count(*) 来自示例组 by trunc(to_date(trunc(time)),'MONTH')
有好心人能帮帮我吗?
您可以使用:
select to_char(time, 'yyyy-mm') as month,
sum(count(*)) over (order by min(time)) as rows_num,
count(*) / extract(day from last_day(time))
from t
group by to_char(time, 'yyyy-mm'), extract(day from last_day(time))
order by min(time);
我对月份的格式设置有所不同,但您可以根据自己的喜好设置格式。
虽然您的查询输出看起来相当简单,但编写内联视图以生成可在外部 SELECT 中使用的值可能是一个优势 SELECT 例如(使用您的示例 table )
Table 和数据
create table example ( id, day_ )
as
select 1, date '2020-02-02' from dual union all -- 2-2-20
select 2, date '2020-01-03' from dual union all -- 3-1-20
select 3, date '2020-02-15' from dual union all -- 15-2-20
select 4, date '2020-03-20' from dual -- 20-3-20
;
第一步(将其用于“内联视图”)
select
to_char( day_, 'MM-YY') month_
, to_char( extract ( day from last_day( day_ ) ) ) lastday_
, count(*) over ( order by to_char( day_, 'MM-YY') ) runningtotal_
, row_number() over ( partition by to_char( day_, 'MM-YY') order by day_ ) rn_
from example ;
-- result
+------+--------+-------------+---+
|MONTH_|LASTDAY_|RUNNINGTOTAL_|RN_|
+------+--------+-------------+---+
|01-20 |31 |1 |1 |
|02-20 |29 |3 |1 |
|02-20 |29 |3 |2 |
|03-20 |31 |4 |1 |
+------+--------+-------------+---+
最终查询
select
month_
, runningtotal_ rows_num
, round( max( rn_ ) / lastday_, 5 ) avg_per_day
, to_char( max( rn_ ) ) || '/' || to_char( lastday_ ) avg_per_day
from (
select
to_char( day_, 'MM-YY') month_
, to_char( extract ( day from last_day( day_ ) ) ) lastday_
, count(*) over ( order by to_char( day_, 'MM-YY') ) runningtotal_
, row_number() over ( partition by to_char( day_, 'MM-YY') order by day_ ) rn_
from example
)
group by month_, runningtotal_, lastday_
order by month_
;
-- result
+------+--------+-----------+-----------+
|MONTH_|ROWS_NUM|AVG_PER_DAY|AVG_PER_DAY|
+------+--------+-----------+-----------+
|01-20 |1 |0.03226 |1/31 |
|02-20 |3 |0.06897 |2/29 |
|03-20 |4 |0.03226 |1/31 |
+------+--------+-----------+-----------+
DBfiddle here.
注意:我不太清楚您需要哪种形式的“AVG_PER_DAY”。只需从外部删除不需要的行 SELECT.
假设我们有一个简单的 table“示例”,如下所示:
id time
1 2-2-20
2 3-1-20
3 15-2-20
4 20-3-20
我想按包含上个月数据的每个月计算行数,并获得每个月的平均数据(按指定月份的行数划分):
month rows_num avg_per_day
1-20 1 1/31
2-20 2+1 2/29
3-20 2+1+1 1/31
我正在考虑是否可以像这样使用 sql 但不会包含上个月的数据并且不知道如何处理平均值:
select count(*) 来自示例组 by trunc(to_date(trunc(time)),'MONTH')
有好心人能帮帮我吗?
您可以使用:
select to_char(time, 'yyyy-mm') as month,
sum(count(*)) over (order by min(time)) as rows_num,
count(*) / extract(day from last_day(time))
from t
group by to_char(time, 'yyyy-mm'), extract(day from last_day(time))
order by min(time);
我对月份的格式设置有所不同,但您可以根据自己的喜好设置格式。
虽然您的查询输出看起来相当简单,但编写内联视图以生成可在外部 SELECT 中使用的值可能是一个优势 SELECT 例如(使用您的示例 table )
Table 和数据
create table example ( id, day_ )
as
select 1, date '2020-02-02' from dual union all -- 2-2-20
select 2, date '2020-01-03' from dual union all -- 3-1-20
select 3, date '2020-02-15' from dual union all -- 15-2-20
select 4, date '2020-03-20' from dual -- 20-3-20
;
第一步(将其用于“内联视图”)
select
to_char( day_, 'MM-YY') month_
, to_char( extract ( day from last_day( day_ ) ) ) lastday_
, count(*) over ( order by to_char( day_, 'MM-YY') ) runningtotal_
, row_number() over ( partition by to_char( day_, 'MM-YY') order by day_ ) rn_
from example ;
-- result
+------+--------+-------------+---+
|MONTH_|LASTDAY_|RUNNINGTOTAL_|RN_|
+------+--------+-------------+---+
|01-20 |31 |1 |1 |
|02-20 |29 |3 |1 |
|02-20 |29 |3 |2 |
|03-20 |31 |4 |1 |
+------+--------+-------------+---+
最终查询
select
month_
, runningtotal_ rows_num
, round( max( rn_ ) / lastday_, 5 ) avg_per_day
, to_char( max( rn_ ) ) || '/' || to_char( lastday_ ) avg_per_day
from (
select
to_char( day_, 'MM-YY') month_
, to_char( extract ( day from last_day( day_ ) ) ) lastday_
, count(*) over ( order by to_char( day_, 'MM-YY') ) runningtotal_
, row_number() over ( partition by to_char( day_, 'MM-YY') order by day_ ) rn_
from example
)
group by month_, runningtotal_, lastday_
order by month_
;
-- result
+------+--------+-----------+-----------+
|MONTH_|ROWS_NUM|AVG_PER_DAY|AVG_PER_DAY|
+------+--------+-----------+-----------+
|01-20 |1 |0.03226 |1/31 |
|02-20 |3 |0.06897 |2/29 |
|03-20 |4 |0.03226 |1/31 |
+------+--------+-----------+-----------+
DBfiddle here.
注意:我不太清楚您需要哪种形式的“AVG_PER_DAY”。只需从外部删除不需要的行 SELECT.