zoukankan      html  css  js  c++  java
  • [每日一题] OCP1z0-047 :2013-07-22 group by 子句





    这道题就是考where group by having的顺序。。。

    答案A不正确:where应该放在group by前面

    答案B不正确:having子句是用多行函数(sum,avg,max,min,count)等做为条件

    答案C不正确:where应该放在group by前面

    参考如下:(其实having 也可以放在group by前面)

    SELECT   column, group_function

    FROM      table

    [WHERE   condition]

    [GROUP BY group_by_expression]

    [HAVING  group_condition]

    [ORDER BY column];

    答案:D


    **********************************************************

    一、group by分组注意:

    drop table t;
    drop table t1;
    create table t(id number,dt date);
    create table t1(id number,dt date);
    insert into t values(1,sysdate);
    insert into t1 values(1,sysdate+1);
    insert into t1 values(1,sysdate+2);
    commit;

    --表中不正确
    select t.id,max(t1.dt) mdt 
    from t,t1 where t.id=t1.id;

    --dual结合select 常量,始终返回一行,不管dual有多少行,所以正确
    --在一般表里会出错,这个世界的规则有普通规则和特殊规则,如果都去遵守普遍规则,那么将会世界太平,特殊规则不用刻意去追求和遵循

    with t as
    (select 1 id,sysdate dt from dual),
    t1 as
    (select 1 id,sysdate+1 dt from dual union all
    select 1,sysdate+2 from dual)
    select t.id,max(t1.dt) mdt 
    from t,t1 where t.id=t1.id;

    --t1.id是多行,不行
    with t as
    (select 1 id,sysdate dt from dual),
    t1 as
    (select 1 id,sysdate+1 dt from dual
     UNION ALL 
    select 1,sysdate+2 from dual)
    select t1.id,max(t1.dt) mdt 
    from t,t1 where t.id=t1.id;

    --让tm来源于表,照样出错,和dual构造都有关系
    with tm as
    (select 1 id,sysdate dt from t),
    t1 as
    (select 1 id,sysdate+1 dt from dual union all
    select 1,sysdate+2 from dual)
    select t1.id,max(t1.dt) mdt 
    from tm,t1 where tm.id=t1.id;

    select dummy from dual;
    --错误
    select dummy from dual having count(*)=1;

    --错误
    with t as
    (select dummy from dual)
    select dummy from t having count(*)=1;

    --用dummy就算取别名也出错,dummy列里不是常量??因为dummy允许多行
    with t as
    (select dummy x from dual)
    select x from t having count(*)=1;
    --正确,不用dummy,因为select 常量 from dual;不管dual有多少行,始终返回一行
    with t as
    (select 'X' x  from dual)
    select x from t having count(*)=1;

    select * from dual;
    --给dual插入一条数据
    insert into sys.dual values('Y');

    ----------------------------------------------------神奇的dual------------------------------------------------------------------
    SQL> select dummy from dual;
     
    DUMMY
    -----
    X
    Y
     
    SQL> select 'X' x from dual;
     
    X
    -
    X
     
    SQL> drop table m;
     
    Table dropped
     
    SQL> create table m(d varchar2(10));
     
    Table created
     
    SQL> insert into m values('a');
     
    1 row inserted
     
    SQL> insert into m values('b');
     
    1 row inserted
     
    SQL> select 'X' x from m;
     
    X
    -
    X
    X


    二、having写在group by前后都一样


    drop table t;
    create table t(id number,name varchar2(10),sal number);
    insert into t values(1,'a',2000);
    insert into t values(1,'b',3000);
    insert into t values(2,'c',1000);
    insert into t values(2,'x',2000);
    insert into t values(3,'d',5000);
    insert into t values(4,'e',4000);
    commit;
    delete from t where id=1;
    --下面的结果是一样的,但是最好用第2种,可读性强
    select id,max(sal),count(*) from t having count(*)>1 group by id;
    select id,max(sal),count(*) from t  group by id having count(*)>1;

    俩个sql有 什么区别?

    1.    select job,sum(sal) from emp t group by job having sum(sal) > 4200

    2.   select job,sum(sal) from emp t having sum(sal) > 4200 group by job 

    查询结果是一样的,具体这俩句有区别吗??

    没有区别,oracle having可以放在前后,常规写法第1种



    三、理解分组

    http://www.itpub.net/thread-1042899-1-1.html


    如何实现比较复杂的分组、小计与合计




    --测试代码
    create table t_dist
    (
      TYPE_CD    NUMBER,
      BUYER_ID   VARCHAR2(50),
      ORDER_DT   DATE,
      SO_ID      VARCHAR2(50) not null,
      STOCK_ID   VARCHAR2(50) not null,
      UNIT_PRICE NUMBER,
      DISCOUNT   NUMBER,
      QTY        NUMBER
    );


    truncate table t_dist;
    insert into t_dist values(1,'CN1001',to_date('2008-04-01','yyyy-mm-dd'),'S9001','29110311',50,10,8);
    insert into t_dist values(1,'CN1001',to_date('2008-04-02','yyyy-mm-dd'),'S9002','29110312',60,20,2);
    insert into t_dist values(1,'CN1001',to_date('2008-04-03','yyyy-mm-dd'),'S9003','29110313',70,15,3);
    insert into t_dist values(2,'CN1001',to_date('2008-04-04','yyyy-mm-dd'),'S9004','29110312',60,15,5);
    insert into t_dist values(2,'CN1001',to_date('2008-04-05','yyyy-mm-dd'),'S9005','29110311',70,10,6);
    insert into t_dist values(3,'CN1001',to_date('2008-04-06','yyyy-mm-dd'),'S9006','29110313',55,20,4);
    insert into t_dist values(3,'CN1001',to_date('2008-04-06','yyyy-mm-dd'),'S9007','29110311',40,10,3);
    insert into t_dist values(3,'CN1001',to_date('2008-04-07','yyyy-mm-dd'),'S9008','29110312',50,50,5);
    insert into t_dist values(3,'CN1001',to_date('2008-04-07','yyyy-mm-dd'),'S9009','29110313',80,10,2);
    insert into t_dist values(1,'CN1001',to_date('2008-04-08','yyyy-mm-dd'),'S9010','29110311',65,10,1);
    commit;


    请问:如何实现如下结果,谢谢!
    即计算按stock_id,type_cd,distount分组,计算每个产品的销售额(qty*unit_price)及销售百分比,并有小计


    STOCK_ID        TYPE_CD        DISCOUNT     AVG_PRICE      SUM_TOT          PCT
    -------------------------------------------------------------------------------------------------
    29110311        1                        10              57.50             465              46.27%
    29110311        2                        10              70.00             420              41.79%
    29110311        3                        10              40.00             120              11.94%
    小计                                                              55.83             1005            100.00%
    29110312        1                        20              60.00             120              17.91%
    29110312        2                        15              60.00             300              44.78%
    29110312        3                        50              50.00             250              37.31%
    小计                                                              56.67             670              100.00%
    29110313        1                        15              70.00             210              35.59%
    29110313        3                        10              80.00             160              27.12%
    29110313        3                        20              55.00             220              37.29%
    小计                                                              68.33             590              100.00%


    哦, 我明白了PCT的意思了, 以后要把问题描述的清楚点![有没有奖励啊? ]


    具体如下:






    SQL> select case when grouping_id(type_cd,discount) = 3 then '小计' else stock_id end stock_id,
      2  type_cd,discount,avg(unit_price ) AVG_PRICE,
      3  sum(qty*unit_price) SUM_TOT,
      4  RATIO_TO_REPORT(sum(qty*unit_price )) over(partition by stock_id)*2 PCT
      5   from t_dist
      6  group by stock_id,rollup((type_cd,discount));


    STOCK_ID                                        TYPE_CD   DISCOUNT  AVG_PRICE    SUM_TOT        PCT
    -------------------------------------------------- ---------- ---------- ---------- ---------- ----------
    29110311                                              1         10       57.5        465 0.46268656
    29110311                                              2         10         70        420 0.41791044
    29110311                                              3         10         40        120 0.11940298
    小计                                                                        56.25       1005          1
    29110312                                              1         20         60        120 0.17910447
    29110312                                              2         15         60        300 0.44776119
    29110312                                              3         50         50        250 0.37313432
    小计                                                                   56.6666666        670          1
    29110313                                              1         15         70        210 0.35593220
    29110313                                              3         10         80        160 0.27118644
    29110313                                              3         20         55        220 0.37288135
    小计                                                                   68.3333333        590          1


    12 rows selected




    QUOTE:
    --------------------------------------------------------------------------------
    原帖由 dingjun123 于 2011-2-23 10:13 发表 


    理解分组的概念
    sum(sum(........之后相当于什么样的分组,后面又来个sum(.............


    当然报错了 
    --------------------------------------------------------------------------------




    还是不理解 ,
    暂不看sum,这里的 分子。分母是一样的啊。只是sum了分母,还是sum了分子;
    相当于 sum(sum(a))/sum(a)  与 sum(a)/sum(sum(a)) ,后面的行的通,前面的怎么可能行不通啊




    理解这个
    with t as
    (select mod(level,2) id from dual connect by level<10 )
    select id,sum(id) from t
    group by id;


    with t as
    (select mod(level,2) id from dual connect by level<10 )
    select-- id,
    sum(sum(id)) from t
    group by id;


    第2句为什么不能有id,因为sum(sum,外面的sum相当于全量分组了,相当于


    with t as
    (select mod(level,2) id from dual connect by level<10 )
    select sum(x) from (
    select id,
    sum(id) x from t
    group by id
    );


    那么当然不能有非汇总列在select里显示啊


    一针见血啊。高~,很耐心的指导啊


    还有个疑问
    select 
    sum(sum(QTY )) over (partition by stock_Id) PCT1 ,
    sum(sum(QTY )) over (partition by stock_Id,grouping(type_cd)) PCT2
      from  t_dist
    group by rollup(stock_id,(type_cd,DISCOUNT))


    PCT1,PCT2有何区别?我实在是想不懂了。


    等价于这个
    select sum(x)  over (partition by stock_Id) PCT1,
    sum(x) over(partition by stock_Id,gp) PCT2
    from (
    select 
    sum(QTY ) x,stock_Id,grouping(type_cd) gp
      from  t_dist
    group by rollup(stock_id,(type_cd,DISCOUNT))
    );


    看红色部分就知道第3个加了grouping的值,那么分区(分组)是不同的,所以两个结果不同


  • 相关阅读:
    ASP.NET使用SWFUpload上传大文件教学
    Gridview自定义分页(转载)
    扩展GridView之个性分页(转载)
    畅通工程
    一个人的旅行
    Stockbroker Grapevine
    Arbitrage
    More is better
    HDU Today
    Minimum Transport Cost
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3206371.html
Copyright © 2011-2022 走看看