我必须生成一份报告,显示每个国家/地区的销售额。 (固定年数)
我设法创建了这个查询:
SELECT sum(dwfactsales.amount) as "2009" INTO v_dwrecord."2009"
FROM dwfactsales
JOIN dwdimcustomer ON dwdimcustomer.customerkey = dwfactsales.customerkey
JOIN dwdimdate ON dwdimdate.datekey = dwfactsales.datekey
WHERE dwdimcustomer.country = 'Australia' and dwdimdate.calenderyear = 2009;
v_dwreport(1) := v_dwrecord;
此查询非常适合收集2009年澳大利亚的销售额。但是,我想对每年和每个国家/地区使用此查询。我可以迭代这些国家,但我似乎无法重复这些年。
我的记录和表格声明为:
TYPE t_DWRECORD IS RECORD(
COUNTRY dwdimcustomer.country%TYPE,
"2009" NUMBER,
"2010" NUMBER,
"2011" NUMBER,
"2012" NUMBER,
"2013" NUMBER,
"2014" NUMBER,
TOTAL NUMBER
);
TYPE t_DWTABLE IS TABLE OF t_DWRECORD INDEX BY BINARY_INTEGER;
我创建了以下代码段:
v_count := 0;
FOR country_rec IN (SELECT DISTINCT country FROM dwdimcustomer order by country asc) LOOP
FOR year_rec IN (SELECT DISTINCT calenderyear FROM dwdimdate order by calenderyear asc) LOOP
SELECT sum(dwfactsales.amount) as "2009" INTO v_dwrecord."2009"
FROM dwfactsales
JOIN dwdimcustomer ON dwdimcustomer.customerkey = dwfactsales.customerkey
JOIN dwdimdate ON dwdimdate.datekey = dwfactsales.datekey
WHERE dwdimcustomer.country = country_rec.country and dwdimdate.calenderyear = year_rec.calenderyear;
v_dwreport(v_count) := v_dwrecord;
v_count := v_count+1;
END LOOP;
END LOOP;
正如您所看到的那样仍然是INTO v_dwrecord."2009"
部分,我想在每次迭代中将其更改为year_rec.calenderyear
。我怎样才能做到这一点?我尝试将EXECUTE IMMEDIATE
与VARCHAR2(500)
变量一起使用,该变量包含动态查询。它看起来像这样:INTO v_dwrecord." || year_rec.calenderyear ||"
。
使用EXECUTE IMMEDIATE
给了我以下错误:
00000 - " SQL命令未正确结束" *原因:
*操作:- 醇>
00000 - "%s:无效的标识符" *原因:
*操作:ORA-00911:无效字符
当我尝试创建动态查询时,一切似乎都会中断。我该如何解决这个问题?我应该继续进行动态查询还是更容易更改v_dwrecord."2009"
?
示例输出:
答案 0 :(得分:1)
您可以使用PIVOT技术来完成您想要的操作,而无需使用FOR和RECORD。它会是这样的:
select dwdimcustomer.country,
sum(case when dwdimdate.calenderyear = 2009
then dwfactsales.amount else 0 end) as "2009",
sum(case when dwdimdate.calenderyear = 2010
then dwfactsales.amount else 0 end) as "2010",
....
sum(case when dwdimdate.calenderyear = 2014
then dwfactsales.amount else 0 end) as "2014",
sum(dwfactsales.amount) as total
FROM dwfactsales
JOIN dwdimcustomer
ON dwdimcustomer.customerkey = dwfactsales.customerkey
JOIN dwdimdate
ON dwdimdate.datekey = dwfactsales.datekey
GROUP BY dwdimcustomer.country
ORDER BY <what ever you want here>;
答案 1 :(得分:1)
我认为您可以使用bulk collect
和pivot
来完成此操作,例如:
示例数据:
create table sales as (
select 'Australia' country, 2009 year, 150 amount from dual union all
select 'Brasil' country, 2009 year, 927 amount from dual union all
select 'Australia' country, 2010 year, 456 amount from dual );
PLSQL块:
declare
type t is record(
country sales.country%type,
s2009 number,
s2010 number,
total number);
type tt is table of t index by binary_integer;
vtt tt;
begin
select country, s2009, s2010, nvl(s2009, 0) + nvl(s2010, 0) total
bulk collect into vtt
from sales
pivot (sum(amount) for year in (2009 as s2009, 2010 as s2010));
-- now you have your collection ready in variable vtt, show some data
for i in 1..vtt.count loop
dbms_output.put_line(i);
dbms_output.put_line(vtt(i).country);
dbms_output.put_line(' 2009: '||vtt(i).s2009);
dbms_output.put_line(' 2010: '||vtt(i).s2010);
dbms_output.put_line('Total: '||vtt(i).total);
end loop;
end;
结果:
1
Brasil
2009: 927
2010:
Total: 927
2
Australia
2009: 150
2010: 456
Total: 606