簡體   English   中英

在定義的時間范圍內計算每日總和與一周中同一天的平均值之間的差異。 SQL 10g Oracle

[英]Calculating difference between daily sum and a average for the same day of the week in defined time range. SQL 10g 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 | 星期幾| 總和| 今年平均星期一| 差和AVG

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

為了清楚起見,我將使用子查詢分解 首先,選擇當前的星期數據。 接下來,子查詢當前一周中某天的總和。 然后,子查詢過去一年中每一天的總和。 然后,將一周中每一天的每一天的每日總和平均。 最后,將兩者合並並顯示差異。

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
;

您可以為此使用分析功能。

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

這將為您提供上一年的每日計數:

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設置的影響。 您可能想使用ALTER SESSION語句將NLS_TERRITORY設置為將導致TO_CHAR('D')在星期一返回1 ,在星期二返回2值。 是支持的區域列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM