【问题标题】:how to aggregate data base per month and previous data with oracle sql如何使用oracle sql聚合每月数据库和以前的数据
【发布时间】:2020-10-13 18:24:41
【问题描述】:

假设我们有一个简单的表格“example”,如下所示:

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 但不包含上个月的数据并且不知道如何处理平均值:

按 trunc(to_date(trunc(time)),'MONTH') 从示例组中选择 count(*)

谁能帮帮我?

【问题讨论】:

    标签: sql database oracle group-by average


    【解决方案1】:

    你可以使用:

    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);
    

    我对月份的格式稍有不同,但您可以根据自己的喜好设置格式。

    【讨论】:

    • 嗨,戈登。谢谢回答。当我尝试运行您的 sql 时,它会出现“00979.00000 - “不是 GROUP BY 表达式””。
    • @yimkong 。 . .固定的。该月的最后一天也需要在group by 中(不会影响任何事情,因为它是恒定的)。
    【解决方案2】:

    虽然查询的输出看起来相当简单,但编写内联视图以生成可在外部 SELECT 中使用的值可能是一个优势,例如(使用您的示例表)

    表格和数据

    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 中删除不需要的行即可。

    【讨论】:

    • 谢谢,真的很有帮助。但数千个数据的结果不正确。但我终于解决了。
    猜你喜欢
    • 2015-02-08
    • 2018-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-11
    • 1970-01-01
    • 2020-02-24
    • 1970-01-01
    相关资源
    最近更新 更多