Oracle话语求教,

Oracle语句求教,急..........................................例如:tab1(销售订单表):编号客户业务员商品

Oracle语句求教,急..........................................
例如:
tab1(销售订单表):
编号         客户           业务员             商品           单价           数量           时间  
SO001      1号店          小明               苹果4          3000          200            2013-07-05
SO002      2号店          小明               苹果5          4200          100            2013-08-05
SO003      1号店          小明               苹果4S        3500          300            2013-07-13
SO004      3号店          小明               苹果4          3000          350            2013-08-09
SO005      2号店          小明               苹果5          4100          600            2013-08-18
SO006      4号店          小明               苹果5S         4500         150            2013-09-07
SO001      3号店          小明               苹果4          3100          100            2013-08-23
SO001      4号店          小明               苹果4S        3600          700            2013-09-16
SO001      1号店          小明               苹果4          3200          400            2013-07-22


希望统计得到苹果4的销售数量:
商品         客户           7月数量    8月数量      9月数量
苹果4       1号店           600            0               0
苹果4       3号店            0              450            0

PS:现在有2个参数日期,一个开始日期和结束日期,根据日期来决定查询的月份。
如参数开始日期:2013-05-16,结束日期:2013-09-17
那么我查询到的月份字段就有5月数量、6月数量、7月数量、8月数量、9月数量,而5月份的数据必须是5月16号之后的,同样,9月统计的数量必须是9月17号之前的。

求语句,我现在的做法是根据2个日期得到月份,然后循环月份,把月份放进SQL语句执行,每个月每个月的查,如果我2个日期区间有10个月,那么我一条数据就要访问10次数据库,导致查询效率大大降低。查询到的数据还没100条,却要花上将近1分钟的时间。像这种直接统计的不会啊,求大神Oracle话语求教,
[解决办法]
test  试试看可以么


CREATE OR REPLACE PROCEDURE P_TEST (B_DATE IN DATE,E_DATE IN DATE)


IS
  V_SQL VARCHAR2(2000);
  CURSOR CURSOR_1 IS 
  SELECT DISTINCT TO_CHAR(T.SJ,'MM') SJ 
  FROM tab1 T
  WHERE T.SJ BETWEEN B_DATE AND E_DATE
  ORDER BY TO_CHAR(T.SJ,'MM'); 
    
    BEGIN
      V_SQL := 'SELECT KH,SP ';
      FOR V_TB IN CURSOR_1
      LOOP
        V_SQL := V_SQL 
[解决办法]
 ',' 
[解决办法]
 'SUM(DECODE(TO_CHAR(T.SJ,''MM''),''' 
              
[解决办法]
 V_TB.SJ 
[解决办法]
 ''',SL,0)) AS "'
[解决办法]
 V_TB.SJ 
[解决办法]
'"';
      END LOOP;
      V_SQL := V_SQL 
[解决办法]
 ' FROM TAB1 T' ;
      V_SQL := V_SQL 
[解决办法]
 ' WHERE T.SJ BETWEEN '
[解决办法]
B_DATE
[解决办法]
 ' AND '
[解决办法]
E_DATE;
      V_SQL := V_SQL 
[解决办法]
 ' GROUP BY KH,SP ORDER BY KH,SP';
     DBMS_OUTPUT.PUT_LINE(V_SQL);
    --EXECUTE IMMEDIATE V_SQL;
    END;


[解决办法]
你可以在程序中根据你的查询条件构造如下sql:
SUM(DECODE(R.MONTH2,'2013-05',A.数量,0)) "5月数量",
SUM(DECODE(R.MONTH2,'2013-06',A.数量,0)) "6月数量",
SUM(DECODE(R.MONTH2,'2013-07',A.数量,0)) "7月数量",
SUM(DECODE(R.MONTH2,'2013-08',A.数量,0)) "8月数量",
SUM(DECODE(R.MONTH2,'2013-09',A.数量,0)) "9月数量"
只需要替换上面的这些,其余的可以参考下面的这段:

SELECT A.商品,A.客户,
SUM(DECODE(R.MONTH2,'2013-05',A.数量,0)) "5月数量",
SUM(DECODE(R.MONTH2,'2013-06',A.数量,0)) "6月数量",
SUM(DECODE(R.MONTH2,'2013-07',A.数量,0)) "7月数量",
SUM(DECODE(R.MONTH2,'2013-08',A.数量,0)) "8月数量",
SUM(DECODE(R.MONTH2,'2013-09',A.数量,0)) "9月数量"
FROM(
SELECT T.商品,T.客户,T.数量, SUBSTR(T.时间,1,7)MONTH2
FROM TAB1 T WHERE T.商品='苹果4'
AND T.时间>= '2013-05-16' AND T.时间<='2013-09-17'
GROUP BY T.商品,T.客户,T.数量,SUBSTR(T.时间,1,7) 
)A
RIGHT JOIN
(
SELECT TO_CHAR(ADD_MONTHS(TO_DATE(
       SUBSTR('2013-05-16',1,7), 'YYYY-MM'), ROWNUM - 1),
       'YYYY-MM') AS MONTH2 FROM DUAL
CONNECT BY ROWNUM <= (SELECT MONTHS_BETWEEN(TO_DATE(
        SUBSTR('2013-09-17',1,7), 'YYYY-MM'),
        TO_DATE(SUBSTR('2013-05-16',1,7), 'YYYY-MM'))FROM DUAL)+1
)R ON A.MONTH2 = R.MONTH2
WHERE A.商品
[解决办法]
A.客户 IS NOT NULL
GROUP BY A.商品,A.客户;

商品   客户  5月数量   6月数量   7月数量  8月数量  9月数量
--------- --------------- ---------- ---------- ---------- ----------
苹果4  3号店   0         0        0        450      0
苹果4  1号店   0         0        600      0        0


表结构:
Name Type         Nullable Default Comments 
---- ------------ -------- ------- -------- 
编号 VARCHAR2(50) Y                         
客户 VARCHAR2(50) Y                         
业务员 VARCHAR2(50) Y                         


商品 VARCHAR2(50) Y                         
单价 VARCHAR2(50) Y                         
数量 VARCHAR2(50) Y                         
时间 VARCHAR2(50) Y         

测试数据:
insert into tab1 (编号, 客户, 业务员, 商品, 单价, 数量, 时间)
values ('SO001', '1号店', '小明', '苹果4', '3000', '200', '2013-07-05');

insert into tab1 (编号, 客户, 业务员, 商品, 单价, 数量, 时间)
values ('SO002', '2号店', '小明', '苹果5', '4200', '100', '2013-08-05');

insert into tab1 (编号, 客户, 业务员, 商品, 单价, 数量, 时间)
values ('SO003', '1号店', '小明', '苹果4s', '3500', '300', '2013-07-13');

insert into tab1 (编号, 客户, 业务员, 商品, 单价, 数量, 时间)
values ('SO004', '3号店', '小明', '苹果4', '3000', '350', '2013-08-09');

insert into tab1 (编号, 客户, 业务员, 商品, 单价, 数量, 时间)
values ('SO005', '2号店', '小明', '苹果5', '4100', '600', '2013-08-18');

insert into tab1 (编号, 客户, 业务员, 商品, 单价, 数量, 时间)
values ('SO006', '4号店', '小明', '苹果5s', '4500', '150', '2013-09-07');

insert into tab1 (编号, 客户, 业务员, 商品, 单价, 数量, 时间)
values ('SO001', '3号店', '小明', '苹果4', '3100', '100', '2013-08-23');

insert into tab1 (编号, 客户, 业务员, 商品, 单价, 数量, 时间)
values ('SO001', '4号店', '小明', '苹果4s', '3600', '700', '2013-09-16');

insert into tab1 (编号, 客户, 业务员, 商品, 单价, 数量, 时间)
values ('SO001', '1号店', '小明', '苹果4', '3200', '400', '2013-07-22');