Chinaunix首页 | 论坛 | 博客
  • 博客访问: 131848
  • 博文数量: 16
  • 博客积分: 2010
  • 博客等级: 大尉
  • 技术积分: 305
  • 用 户 组: 普通用户
  • 注册时间: 2007-11-15 10:25
文章分类

全部博文(16)

文章存档

2010年(16)

我的朋友

分类: Oracle

2010-01-06 20:55:16

测试目的:

    第一道:显示出 业绩 大于同一地区平均值的 合同id  姓名 地区 业绩
    第二道:把同一地区的 平均业绩 地区 插入到新表中 (新表只包含两个字段即:平均业绩 地区)
    不仅限于这两个比较简单的SQL语句,本文还包括几个比较简单的分析函数的使用,属于入门级。

测试数据:

    id sname smoney sprovince
    1 zhangsan 2098 A
    2 lisi 3000 B
    3 wangwu 6789 C
    4 liumazi 4587 C
    5 dongjiu 3298 B
    6 shiga 4567 A
     
    注:id:合同id  sname:姓名     smoney :业绩     sprovince:地区

测试环境数据:

    
    DROP TABLE TT PURGE;

    CREATE TABLE TT
    ( ID NUMBER(5),
      SNAME VARCHAR2(20),
      SMONEY NUMBER(8,2),
      SPROVINCE VARCHAR2(2)
    );

    INSERT INTO TT(ID,SNAME,SMONEY,SPROVINCE)
    VALUES(1,'ZHANGSAN',2098,  'A');
    INSERT INTO TT(ID,SNAME,SMONEY,SPROVINCE)
    VALUES(2,'LISI',3000,  'B');
    INSERT INTO TT(ID,SNAME,SMONEY,SPROVINCE)
    VALUES(3,'WANGWU',  6789,  'C');
    INSERT INTO TT(ID,SNAME,SMONEY,SPROVINCE)
    VALUES(4,'LIUMAZI', 4587,  'C');
    INSERT INTO TT(ID,SNAME,SMONEY,SPROVINCE)
    VALUES(5,'DONGJIU', 3298,  'B');
    INSERT INTO TT(ID,SNAME,SMONEY,SPROVINCE)
    VALUES(6,'SHIGA', 4567,  'A');
    COMMIT;

解决:

  第一道:显示出 业绩 大于同一地区平均值的 合同id  姓名 地区 业绩

SELECT A.ID, A.SNAME, A.SPROVINCE, A.SMONEY
      FROM TT A
     WHERE SMONEY > (SELECT SUM(B.SMONEY) / COUNT(1)
                       FROM TT B
                      WHERE B.SPROVINCE = A.SPROVINCE);

            ID SNAME SP SMONEY
    ---------- -------------------- -- ----------

             3 WANGWU  C 6789
             5 DONGJIU B 3298
             6 SHIGA   A 4567

  第二道:把同一地区的 平均业绩 地区 插入到新表中 (新表只包含两个字段即:平均业绩 地区)


CREATE TABLE TT_SUM
    AS
    SELECT SPROVINCE, SUM(SMONEY)/COUNT(1) AVG_PRO
      FROM TT
    GROUP BY SPROVINCE;

    SQL> select * from tt_sum;

    SP AVG_PRO
    -- ----------

    A 3332.5
    B 3149
    C 5688

补充:

    该部分将展示RANK、ROW_NUMBER()和DENSE_RANK()以及在分区功能中使用汇总函数的SQL特性。

    SELECT * FROM TT;

    第三道:查询每个人在地区内的排名(按照业绩顺序--由高到低)


SELECT TT.*,
           ROW_NUMBER() OVER(PARTITION BY TT.SPROVINCE ORDER BY SMONEY DESC)
      FROM TT;


第四道:查询各个地区排名第一的销售员以及业绩



SELECT *
      FROM (SELECT TT.*,
                   ROW_NUMBER() OVER(PARTITION BY TT.SPROVINCE ORDER BY SMONEY DESC) ORD
              FROM TT)
     WHERE ORD < 2;

    --补充数据


    INSERT INTO TT VALUES (7, 'thinkaw', 4567, 'A');

    SELECT TT.*,
           ROW_NUMBER() OVER(PARTITION BY TT.SPROVINCE ORDER BY SMONEY DESC) row_number
      FROM TT;

            ID SNAME SMONEY SP ROW_NUMBER
    ---------- -------------------- ---------- -- ----------

             7 thinkaw 4567 A 1
             6 SHIGA 4567 A 2
             1 ZHANGSAN 2098 A 3
             5 DONGJIU 3298 B 1
             2 LISI 3000 B 2
             3 WANGWU 6789 C 1
             4 LIUMAZI 4587 C 2

    已选择7行。


 注:此时对于A Porvince 'shiga'和'thinkaw'的销售业绩是一样的,那么如果还是要查询第三道中的问题,并且明确指出,我们要查询出并列第一的销售员信息。



SELECT TT.*,
           DENSE_RANK() OVER(PARTITION BY TT.SPROVINCE ORDER BY SMONEY DESC) dense_rank
      FROM TT;

            ID SNAME SMONEY SP DENSE_RANK
    ---------- -------------------- ---------- -- ----------

             7 thinkaw  4567 A 1
             6 SHIGA    4567 A 1
             1 ZHANGSAN 2098 A 2
             5 DONGJIU  3298 B 1
             2 LISI     3000 B 2
             3 WANGWU   6789 C 1
             4 LIUMAZI  4587 C 2

    已选择7行。
        
    SELECT *
      FROM (SELECT TT.*,
                   DENSE_RANK() OVER(PARTITION BY TT.SPROVINCE ORDER BY SMONEY DESC) ORD
              FROM TT)
     WHERE ORD < 2;

            ID SNAME SMONEY SP ORD
    ---------- -------------------- ---------- -- ----------

             6 SHIGA   4567 A 1
             7 thinkaw 4567 A 1
             5 DONGJIU 3298 B 1
             3 WANGWU  6789 C 1


另外对于这组分析函数还有一个rank函数,我们对比一下


SELECT TT.*,
           DENSE_RANK() OVER(PARTITION BY TT.SPROVINCE ORDER BY SMONEY DESC) DENSE_RANK,
           ROW_NUMBER() OVER(PARTITION BY TT.SPROVINCE ORDER BY SMONEY DESC) ROW_NUMBER,
           RANK() OVER(PARTITION BY TT.SPROVINCE ORDER BY SMONEY DESC) RANK
      FROM TT;

            ID SNAME SMONEY SP DENSE_RANK ROW_NUMBER RANK
    ---------- -------------------- ---------- -- ---------- ---------- ----------

             7 thinkaw  4567 A 1 1 1
             6 SHIGA    4567 A 1 2 1
             1 ZHANGSAN 2098 A 2 3 3
             5 DONGJIU  3298 B 1 1 1
             2 LISI     3000 B 2 2 2
             3 WANGWU   6789 C 1 1 1
             4 LIUMAZI  4587 C 2 2 2

    已选择7行。
      
     


注:对比一下显示,然后根据具体情况选择使用

    同其他汇总函数结合使用的分析函数

  第五道:查询每个地区的业绩总额
    SELECT TT.SPROVINCE, SUM(TT.SMONEY) SUM_MONEY
      FROM TT
     GROUP BY TT.SPROVINCE;

  第六道:查询每个销售员销售业绩占本地区销售总额的百分比

SELECT TT.*,
           round( TT.SMONEY / SUM(TT.SMONEY) OVER(PARTITION BY TT.SPROVINCE) , 4) * 100 PERCENT_INFO,
           SUM(TT.SMONEY) OVER(PARTITION BY TT.SPROVINCE) SUM_MONEY
      FROM TT;

            ID SNAME SMONEY SP PERCENT_INFO SUM_MONEY
    ---------- -------------------- ---------- -- ------------ ----------

             6 SHIGA    4567 A 40.66 11232
             1 ZHANGSAN 2098 A 18.68 11232
             7 thinkaw  4567 A 40.66 11232
             2 LISI     3000 B 47.63 6298
             5 DONGJIU  3298 B 52.37 6298
             3 WANGWU   6789 C 59.68 11376
             4 LIUMAZI  4587 C 40.32 11376

    已选择7行。

结论:

    1 Over ( Partition by xxxx ) 此部分的功能就是按照xxx把数据分成各个子区间,然后允许在子区间上进行求和、求平均等汇总功能的使用;
    2 ROW_NUMBER、DENSE_RANK、RANK对分区上数据的不同排序方式

参考:


阅读(1381) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-02-10 21:58:53

第四道比较特殊,可以有通用写法。 select sname,smoney from tt where (smoney,sprovince) in (select distinct max(smoney),sprovince from tt group by sprovince);