[英]Oracle SQL Loop to fill future dates
您可以為此使用 model 子句。 可能有一種更有效/更清潔的方式,但假設您有一張包含年、周和收入的表格,那么:
select year, week, revenue
from your_table
model
dimension by (year, week)
measures (revenue, 0 week_chg)
rules upsert sequential order (
week_chg[any, any] =
revenue[cv(year) - 1, cv(week)]/revenue[cv(year) - 1, cv(week) - 1],
revenue[any, any] =
coalesce(
revenue[cv(), cv()],
round(revenue[cv(year), cv(week) - 1] * week_chg[cv(year), cv(week)], 2)
)
)
產生:
年 | 星期 | 收入 |
---|---|---|
2021 | 1 | 1000 |
2021 | 2 | 2000 |
2021 | 3 | 3000 |
2021 | 4 | 8000 |
2021 | 5 | 9000 |
2021 | 6 | 8750 |
2021 | 7 | 9500 |
2021 | 8 | 10000 |
2022 | 1 | 10000 |
2022 | 2 | 12000 |
2022 | 3 | 15000 |
2022 | 4 | 13500 |
2022 | 5 | 15187.5 |
2022 | 6 | 14765.63 |
2022 | 7 | 16031.26 |
2022 | 8 | 16875.01 |
這將依次應用兩個規則。 首先:
week_chg[any, any] =
revenue[cv(year) - 1, cv(week)]/revenue[cv(year) - 1, cv(week) - 1]
計算出上一年的周變化值 - 一年前和同一周的收入除以一年前和一周前的收入。
然后
revenue[any, any] =
coalesce(
revenue[cv(), cv()],
round(revenue[cv(year), cv(week) - 1] * week_chg[cv(year), cv(week)], 2)
將當前維度的收入設置為實際收入值(如果有); 否則是前一周的收入(關鍵是,它可能只是自己計算出來的)乘以匹配的周變化值。 然后將該值四舍五入到小數點后兩位,這似乎是您想要的。
(由於舍入差異,最后兩個結果與您的示例略有不同。如果week_chg
舍入到小數點后 6 位,則 2002 年第 8 周的結果正好為 16875,但第 7 周和第 6 周則不同。)
如果您分別需要它們,小提琴有一個顯示兩個值的中間結果。
假設你有桌子:
CREATE TABLE this_year (week, revenue) AS
SELECT 1, 10000 FROM DUAL UNION ALL
SELECT 2, 12000 FROM DUAL UNION ALL
SELECT 3, 15000 FROM DUAL UNION ALL
SELECT 4, 13500 FROM DUAL;
CREATE TABLE last_year (week, revenue) AS
SELECT 1, 5000 FROM DUAL UNION ALL
SELECT 2, 6000 FROM DUAL UNION ALL
SELECT 3, 7000 FROM DUAL UNION ALL
SELECT 4, 8000 FROM DUAL UNION ALL
SELECT 5, 9000 FROM DUAL UNION ALL
SELECT 6, 8750 FROM DUAL UNION ALL
SELECT 7, 9500 FROM DUAL UNION ALL
SELECT 8, 10000 FROM DUAL;
然后您可以使用MODEL
子句:
SELECT week,
revenue
FROM (
SELECT ly.week AS week,
ly.revenue AS ly_revenue,
ty.revenue AS ty_revenue
FROM last_year ly
LEFT OUTER JOIN this_year ty
ON (ly.week = ty.week)
)
MODEL
DIMENSION BY (week)
MEASURES (
ly_revenue,
ty_revenue,
0 AS ly_multiplier,
0 AS revenue
)
RULES AUTOMATIC ORDER (
revenue[1] = COALESCE(
ty_revenue[1],
ly_revenue[1]
),
revenue[week>1] = COALESCE(
ty_revenue[cv()],
revenue[cv()-1] * ly_revenue[cv()]/ly_revenue[cv()-1]
)
);
哪個輸出:
星期 收入 1 10000 2 12000 3 15000 4 13500 6 14765.625 5 15187.5 7 16031.25 8 16875
db<> 在這里擺弄
首先請看一下去年的每周變化數。 當您將第 4 周的收入乘以 8000 x 第 5 周的變化 1.125 = 9000 時,您將獲得第 5 周的收入。 當您將第 5 周和第 6 周的變化相乘時 = 1.125 x 0.972222 = 1,093749。 然后,當您將此數字乘以第 4 周的收入 8000 = 時,您將獲得第 6 周的收入 8750。
所以類似的邏輯,你需要保留你知道的最新記錄。 所以在這種情況下,今年是第 4 周。 然后乘以每周變化值。 為此,讓我們從數學中獲得幫助。 您可以將每個值的對數相加,然后取結果的指數。 然后你得到每周乘以變化的值,然后將結果乘以收入。
select *
from (
select '1' as week, 10000 as revenue
union all
select '2' as week, 12000 as revenue
union all
select '3' as week, 15000 as revenue
union all
select '4' as week, 13500 as revenue
)m
union all
-- future
select
ly.week,
(m.revenue * exp(sum(log(ly2.week_chg)))) as revenue_future
from (
select '4' as week, 13500 as revenue -- you can get latest record via rownum, i will share query below
)m
join (
select '4' as week, 8000 as revenue_ly, null as week_chg
union all
select '5' as week, 9000 as revenue_ly, 1.125 as week_chg
union all
select '6' as week, 8750 as revenue_ly, 0.972222 as week_chg
union all
select '7' as week, 9500 as revenue_ly, 1.085714 as week_chg
union all
select '8' as week, 10000 as revenue_ly, 1.052632 as week_chg
)ly
on ly.week > m.week
join (
select '4' as week, 8000 as revenue_ly, null as week_chg
union all
select '5' as week, 9000 as revenue_ly, 1.125 as week_chg
union all
select '6' as week, 8750 as revenue_ly, 0.972222 as week_chg
union all
select '7' as week, 9500 as revenue_ly, 1.085714 as week_chg
union all
select '8' as week, 10000 as revenue_ly, 1.052632 as week_chg
)ly2
on ly.week >= ly2.week
where 1 = 1
group by ly.week
從主表獲取最新記錄:
select week, revenue
from (
select m.*,
row_number() over(partition by 1 order by week desc) rn
from (
select '1' as week, 10000 as revenue
union all
select '2' as week, 12000 as revenue
union all
select '3' as week, 15000 as revenue
union all
select '4' as week, 13500 as revenue
)m
)dt
where 1 = 1
and rn = 1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.