2

嗨,我正在处理数据,主要取决于一周中的哪一天。数据在表格中格式化日期 - 位置 - 计数/数字。有多个不同的位置。我能够使用一周中的每一天对我的数据进行排序。

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 | 星期几 | 总和 | 今年平均周一 | 差值总和

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

4

3 回答 3

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
;

最后一个注释是 about TO_CHAR('D'),用于获取day_of_week值。由于您对相同的结果使用不同的方法,您可能不知道结果TO_CHAR('D')NLS_TERRITORY设置的影响。您可能希望使用ALTER SESSION语句设置为星期一、星期二等返回NLS_TERRITORY的值。以下是支持的地区列表。TO_CHAR('D')12

于 2013-09-20T08:08:32.617 回答
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);
于 2013-09-17T06:46:06.330 回答
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
;
于 2013-09-16T16:22:03.547 回答