[英]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.