我有點不清楚你在掙扎哪一部分,或者爲什麼你是指許多嵌套的SQL。在沒有任何樣本數據,我不得不做出一些了:
create table t42 (my_date date, my_value number);
insert into t42 values (date '2006-01-31', 0601);
insert into t42 values (date '2006-12-31', 0612);
insert into t42 values (date '2007-01-31', 0701);
insert into t42 values (date '2007-12-31', 0712);
insert into t42 values (date '2008-01-31', 0801);
insert into t42 values (date '2008-12-31', 0812);
insert into t42 values (date '2009-01-31', 0901);
insert into t42 values (date '2009-12-31', 0912);
insert into t42 values (date '2010-01-31', 1001);
insert into t42 values (date '2010-12-31', 1012);
insert into t42 values (date '2011-01-31', 1101);
insert into t42 values (date '2011-12-31', 1112);
insert into t42 values (date '2012-01-31', 1201);
insert into t42 values (date '2012-02-29', 1202);
insert into t42 values (date '2012-03-31', 1203);
insert into t42 values (date '2012-04-30', 1204);
insert into t42 values (date '2012-05-31', 1205);
然後,您可以使用一個內部查詢產生期間/年/月的「標籤」,並插入一個空場被責令結果,再加上你的價值觀真正感興趣。然後,一個外部查詢做任何sum
,count
等
select label, sum(my_value), count(1)
from
(
select
case when my_date < trunc(sysdate, 'YYYY') - interval '4' year then
'Before ' || to_char(trunc(sysdate, 'YYYY')
- interval '5' year, 'YYYY')
when my_date < trunc(sysdate, 'YYYY') - interval '1' year then
to_char(my_date, 'YYYY')
else to_char(my_date, 'Mon YYYY')
end as label,
case when my_date < trunc(sysdate, 'YYYY') - interval '4' year then
to_char(trunc(sysdate, 'YYYY') - interval '5' year, 'YYYYMM')
when my_date < trunc(sysdate, 'YYYY') - interval '1' year then
to_char(my_date, 'YYYY') || '01'
else to_char(my_date, 'YYYYMM')
end as order_field,
my_value
from t42
)
group by label, order_field
order by order_field;
我使用trunc(sysdate, 'YYYY')
找到當年開始,然後使用interval
去回溯五年,並且基於那些生產label
和order_field
假專欄「水桶」。這樣使用case
可以讓我擁有不同的水桶 - 一個超過五年的水桶,一年之前的一年,一年之後的水桶。
LABEL SUM(MY_VALUE) COUNT(1)
----------------- ------------- ----------
Before 2007 2626 4
2008 1613 2
2009 1813 2
2010 2013 2
Jan 2011 1101 1
Dec 2011 1112 1
Jan 2012 1201 1
Feb 2012 1202 1
Mar 2012 1203 1
Apr 2012 1204 1
May 2012 1205 1
我只打表一次,這樣的表現應該取決於你如何提取原始數據(你的連接和條件),而不是你如何操縱它。很明顯,你可以用你當前替換t42
你的兩個表之間的連接,並找出你感興趣的領域。
我建議你切換到ANSI連接語法,而不是Oracle的老(+)
記法外連接。這不涉及任何沒有任何數據的年份或月份,但您的原始大綱也沒有,因此這可能不是問題。而且,如何生成或至少顯示「年份總和」值可能取決於您的客戶。
分離出標籤生成到一個視圖,以使其可重複使用,讓你發現沒有數據的時間段:
create or replace view v42 (period_label, period_order, period_start, period_end)
as
select 'Before ' || to_char(trunc(sysdate, 'YYYY') - interval '5' year, 'YYYY'),
'197001',
date '1970-01-01',
trunc(sysdate, 'YYYY') - interval '4' year - interval '1' second
from dual
union
select to_char(year_start, 'YYYY'),
to_char(year_start, 'YYYY') || '01',
year_start,
year_start + interval '1' year - interval '1' second
from (
select add_months(trunc(sysdate, 'YYYY'), - 12 * (level + 1)) as year_start
from dual connect by level <= 3
)
union
select to_char(month_start, 'Mon YYYY'),
to_char(month_start, 'YYYYMM'),
month_start,
month_start + interval '1' month - interval '1' second
from (
select add_months(trunc(sysdate, 'MM'), 1 - level) as month_start
from dual connect by level <= 12 + to_number(to_char(sysdate, 'MM'))
);
這是產生你原本的標籤;如果您希望顯示所有年份單獨刪除union
的第一部分,並且您可以調整connect by
子句以更改按月顯示的年份。 (你可能會參數化,但這可能會有點遠)。
你有三類「桶」,一個按月分類,一個按年分類,然後是過去的任何東西都可以捕獲所有的東西;聯盟的每個部分都會處理其中一個部分,爲每個類中的所有桶生成期間開始和結束日期,以及稍後訂購的標籤和某些內容。查看視圖,也可以分別查看每個select
,看看他們在做什麼。
然後將該視圖加入到您的數據表或表中;與左外連接,如果你想不匹配的數據顯示標籤:
select v.period_label, nvl(sum(t.my_value), 0), count(t.my_value)
from v42 v
left join t42 t on t.my_date between v.period_start and v.period_end
group by v.period_label, v.period_order
order by v.period_order;
PERIOD_LABEL NVL(SUM(T.MY_VALUE),0) COUNT(T.MY_VALUE)
----------------- ---------------------- -----------------
Before 2007 2626 4
2008 1613 2
2009 1813 2
2010 2013 2
Jan 2011 1101 1
Feb 2011 0 0
...
Nov 2011 0 0
Dec 2011 1112 1
...
對不起,這是我第一次post.My甲骨文技能生疏,只能再次把它撿起來幾個月前。感謝您的詳細解釋和建議。您的解決方案解決了我的問題的90%。有幾個細節我仍然在苦苦掙扎。 1:有20多種產品,每種產品都需要一張結果表,外觀完全相同。 2:並非所有產品都具有「my_date」值來繪製標籤。 3:最近3年需要總數,但可以在水晶報表上計算。這基本上是一個產品銷售的OLAP立方體分析,具有指定期限,必須在SP報告中寫入Crystal報告。 – thzNewbie
@thzNewbie - 這真的不是一個批評,更多的是我不確定我是否真的在解決你的問題 - 看起來我很高興,主要是無論如何。如果'桶'是你需要的,那麼我猜你的主要問題是將底層數據轉化爲正確的形式和位置 - 用'from'替換'from t42'(select ... from table_a join table_b ...在哪裏......)等等。你當然可以有更多的列,你只需要把它們放在你的內部select中,然後將它們聚合或者將它們添加到'group by'中。 –
任何解決標籤問題的解決方案,以便它始終創建一個固定的視圖?除了創建一個表與我想要的指定日期範圍的組合。即生成這個年份和月份組合的列表 – thzNewbie