计算每日总和与定义时间范围内同一天的平均值之间的差异。 SQL 10g Oracle

时间:2013-09-16 12:56:32

标签: sql oracle

您好我正在使用的数据主要取决于一周中的哪一天。数据在表格中格式化 日期 - 位置 - 计数/数量。 有多个不同的立场。 我能够使用。

对每周的每一天的数据进行排序
select MOD(to_char(time, 'J'),7),  
       sum(COUNT))                  
 from TABLE
where time > sysdate -x
group by to_char(time, 'J')
order by to_char(time, 'J');

根据星期几输出每日总和。

现在我能够获得一年中一周中一天的平均值。 此代码仅输出星期日的平均值

SELECT AVG(asset_sums)  
  FROM  (
          select MOD(to_char(time, 'J'),7), 
                 sum(COUNT)) as asset_sums
            from table
           where time > sysdate -365
             and MOD(TO_CHAR(time, 'J'), 7) + 1 IN (7)
           group by to_char(time, 'J')
           order by to_char(time, 'J') 
        );

我的目标是能够获得每日总和与一周中特定日期的年平均值相比较的表格。 例如,星期一的年平均数为57,星期二为60。 本周我的星期一是59,星期二是57.表的输出是 星期一+2,星期二-3。 什么是最简单的方法/最有效的方法? 谢谢你的帮助。

编辑:我的数据格式

  

日期:yyyy-mm-dd |地点:xxxx | (客户数量)0到10000

   2013-09-16 | AAAA | 1534
   2013-09-16 | AAAB | 534
   2013-09-17 | AAAA | 1434
   2013-09-17 | AAAC | 834
   2013-09-18 | AAAA | 134
   2013-09-18 | AAAD | 183

需要的输出

  

2013-09-16 |星期几|总和|今年平均周一|差异Sum-AVG

     

2013-09-16 | 1(=星期一)| 2068年| 2015年| 53

3 个答案:

答案 0 :(得分:0)

为清楚起见,我将使用subquery factoring。首先,选择当前的周数据。接下来,子查询当前一周的总和。然后,查询过去一年中每天的总和。然后,平均每周每天的每日总和。最后,加入两个并显示差异。

with

this_week as (
    select 
        time
    from table
    where time > x - 7
    group by time
),

this_week_dly_sum as (
    select 
        to_char(time, 'd') day,
        sum(count) sum
    from this_week
    group by to_char(time, 'd')
),

this_year_dly_sum as (
    select 
        time,
        sum(count) sum
    from table
    where time > x - 365
    group by time
),

this_year_dly_avg as (
    select
        to_char(day, 'd'),
        avg(sum) avg
    from this_year_dly_sum
    group by to_char(day, 'd')
)

select
    this_week.time,
    to_char(this_week.time, 'day') day of week,
    this_week_dly_sum.sum,
    this_year_dly_avg.avg,
    this_week_dly_sum.sum - this_year_dly_avg.avg difference    
from this_week
inner join this_week_dly_sum
    on to_char(this_week.time, 'd') = this_week_dly_sum.day
inner join this_year_dly_avg
    on to_char(this_week.time, 'd').day = this_year_dly_avg.
group by time
;

答案 1 :(得分:0)

您可以使用分析功能。

select date1,  to_char(date1, 'd'), 
       sum(val) over(partition by to_char(date1, 'd')),
       avg(val) over(partition by to_char(date1, 'd')), 
       sum(val) over(partition by to_char(date1, 'd'))-
       avg(val) over(partition by to_char(date1, 'd'))
from table1
time > add_month(sysdate,-12);

答案 2 :(得分:0)

这将为您提供去年的每日计数:

SELECT TRUNC(time, 'DD') AS date,
       SUM(count) AS asset_sum
  FROM yourtable
 WHERE time > SYSDATE - 365
 GROUP BY TRUNC(time, 'DD')

您可以修改它以额外返回指定范围的每周每日平均值:

SELECT TRUNC(time, 'DD') AS date,
       SUM(count) AS asset_sum,
       AVG(SUM(count)) OVER
         (PARTITION BY TO_CHAR(TRUNC(time, 'DD'), 'D')) AS asset_sum_avg
  FROM yourtable
 WHERE time > SYSDATE - 365
 GROUP BY TRUNC(time, 'DD')

此时您拥有所需的所有初始数据,但可能需要更多天数。您可以将上述查询用作派生表,将行限制为date > SYSDATE - x

的行
  WITH last_year_by_day AS
       (
       SELECT TRUNC(time, 'DD') AS date,
              SUM(count) AS asset_sum,
              AVG(SUM(count)) OVER
                (PARTITION BY TO_CHAR(TRUNC(time, 'DD'), 'D')) AS asset_sum_avg
         FROM yourtable
        WHERE time > SYSDATE - 365
        GROUP BY TRUNC(time, 'DD')
       )
SELECT date,
       TO_CHAR(TRUNC(time, 'DD'), 'D') AS day_of_week,
       asset_sum,
       asset_sum_avg,
       asset_sum - asset_sum_avg AS asset_sum_diff
  FROM last_year_by_day
 WHERE date > SYSDATE - x
;

由于某些表达式被重复多次,因此重新考虑查询以避免重复是一个好主意。这是一种方式:

  WITH last_year AS
       (
       SELECT TRUNC(time, 'DD') AS date,
              TO_CHAR(time, 'D') AS day_of_week,
              count
         FROM yourtable
        WHERE time > SYSDATE - 365
       ),
       last_year_by_day AS
       (
       SELECT date,
              day_of_week,
              SUM(count) AS asset_sum,
              AVG(SUM(count)) OVER (PARTITION BY day_of_week) AS asset_sum_avg
         FROM last_year
        GROUP BY date, day_of_week
       )
SELECT date,
       day_of_week,
       asset_sum,
       asset_sum_avg,
       asset_sum - asset_sum_avg AS asset_sum_diff
  FROM last_year_by_day
 WHERE date > SYSDATE - x
;

最后一个注释是关于TO_CHAR('D'),用于获取day_of_week值。由于您对相同的结果使用了不同的方法,因此您可能不会意识到TO_CHAR('D')设置会影响NLS_TERRITORY的结果。您可能希望使用NLS_TERRITORY语句将TO_CHAR('D')设置为导致1周一返回2,周二{{1}}等等的值{ {3}}是支持的地区列表。