精华内容
下载资源
问答
  • 如果已经存在索引,建议你先重建索引先,因为大数据的索引维护到了一阶段就是乱的,一般建议重建。建立好的一般可以获得几十倍的速度提升。 最大数据量的放在最前,最小的放在最后面。sql是从最后面开始反向...
    1. 首先要建立适当的索引。sql在索引字段不要加函数,保证索引起效。如果是复合索引注意在sql的顺序。如果已经存在索引,建议你先重建索引先,因为大数据表的索引维护到了一个阶段就是乱的,一般建议重建。建立好的一般可以获得几十倍的速度提升。
    2. 最大数据量的表放在最前,最小的表放在最后面。sql是从最后面开始反向解析的。
    3. 其次是要把最有效缩小范围的条件放到sql末尾去。尤其是主键或者索引字段的条件。
    4. 保证你sql的算法合理性。保证复杂度和空间度的合理性。
    5. 必要时候使用存储过程。提升30%-40%的速度
    6. 建议你分页读取不要一下读完所有的数据。(使用rownum),一下子数据太多会使得内存不够用的。

    如果这些都做了还不满意的话,可以考虑建立几个表空间,然后按照一个算法将各个表的数据,平均的放在各个表空间内(分表分区),在select的时候数据库就会使用多线程到各个表空间索引数据,这个一般不是上千万级的表是不用的。 也不是所有人都会用。


    Oracle多表连接,提高效率,性能优化

    执行路径:ORACLE的这个功能大大地提高了SQL的执行性能并节省了内存的使用:我们发现,单表数据的统计比多表统计的速度完全是两个概念.单表统计可能只要0.02秒,但是2张表联合统计就可能要几十表了.这是因为ORACLE只对简单的表提供高速缓冲(cache buffering) ,这个功能并不适用于多表连接查询..数据库管理员必须在init.ora中为这个区域设置合适的参数,当这个内存区域越大,就可以保留更多的语句,当然被共享的可能性也就越大了.

    当你向ORACLE提交一个SQL语句,ORACLE会首先在这块内存中查找相同的语句.
    这里需要注明的是,ORACLE对两者采取的是一种严格匹配,要达成共享,SQL语句必须
    完全相同(包括空格,换行等).

    共享的语句必须满足三个条件:
    A.字符级的比较:
    当前被执行的语句和共享池中的语句必须完全相同.
    例如:

         SELECT * FROM EMP;

    和下列每一个都不同

               SELECT * from EMP;
               Select * From Emp;
               SELECT       *      FROM EMP;

    B.两个语句所指的对象必须完全相同:

    用户对象名 如何访问

    Jack   sal_limit                private synonym
    Work_city                       public synonym
    Plant_detail                    public synonym
    Jill   sal_limit                private synonym
    Work_city                       public synonym
    Plant_detail                    table owner

    考虑一下下列SQL语句能否在这两个用户之间共享.

    SQL 能否共享 原因

    select max(sal_cap) from sal_limit; 不能 每个用户都有一个private synonym - sal_limit , 它们是不同的对象
    select count(*) from work_city where sdesc like 'NEW%'; 能 两个用户访问相同的对象public synonym - work_city
    select a.sdesc,b.location from work_city a , plant_detail b where a.city_id = b.city_id 不能 
    用户jack 通过private synonym访问plant_detail 而jill 是表的所有者,对象不同.

    C.两个SQL语句中必须使用相同的名字的绑定变量(bind variables)
    例如:第一组的两个SQL语句是相同的(可以共享),而第二组中的两个语句是不同的(即使在运行时,赋于不同的绑定变量相同的值)

    a.
    select pin , name from people where pin = :blk1.pin;
    select pin , name from people where pin = :blk1.pin;
    b.
    select pin , name from people where pin = :blk1.ot_ind;
    select pin , name from people where pin = :blk1.ov_ind;

    重点关注1:选择最有效率的表名顺序(只在基于规则的优化器中有效)重点关注
    ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving table)将被最先处理. 在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表.当ORACLE处理多个表时, 会运用排序及合并的方式连接它们.首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个表),最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并.

    例如: 表 TAB1 16,384 条记录
    表 TAB2 1 条记录

    选择TAB2作为基础表 (最好的方法)

    select count(*) from tab1,tab2    执行时间0.96

    选择TAB2作为基础表 (不佳的方法)

    select count(*) from tab2,tab1    执行时间26.09

    如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表.

    例如:EMP表描述了LOCATION表和CATEGORY表的交集.

    SELECT *
    FROM LOCATION L, CATEGORY C, EMP E
    WHERE E.EMP_NO BETWEEN 1000 AND 2000
        AND E.CAT_NO = C.CAT_NO
        AND E.LOCN = L.LOCN

    将比下列SQL更有效率

    SELECT *
    FROM EMP E, LOCATION L, CATEGORY C
    WHERE E.CAT_NO = C.CAT_NO
        AND E.LOCN = L.LOCN
        AND E.EMP_NO BETWEEN 1000 AND 2000

    重点关注2:WHERE子句中的连接顺序.重点关注

    ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.
    例如:

    --(低效,执行时间156.3秒)
    SELECTFROM EMP E
    WHERE   SAL > 50000
    AND     JOB = ‘MANAGER’
    AND     25 < (SELECT COUNT(*) FROM EMP
    WHERE MGR=E.EMPNO);
    --(高效,执行时间10.6秒)
    SELECTFROM EMP E
    WHERE 25 < (SELECT COUNT(*) FROM EMP
                  WHERE MGR=E.EMPNO)
    AND     SAL > 50000
    AND     JOB = ‘MANAGER’;

    重点关注3:SELECT子句中避免使用 ‘ * ‘ .重点关注

    当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用 ‘*’ 是一个方便的方法.不幸的是,这是一个非常低效的方法. 实际上,ORACLE在解析的过程中, 会将’*’ 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间.

    减少访问数据库的次数

    当执行每条SQL语句时, ORACLE在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等等. 由此可见, 减少访问数据库的次数 , 就能实际上减少ORACLE的工作量.
    例如,
    以下有三种方法可以检索出雇员号等于0342或0291的职员.

    方法1 (最低效)

         SELECT EMP_NAME , SALARY , GRADE
         FROM EMP
         WHERE EMP_NO = 342;
          SELECT EMP_NAME , SALARY , GRADE
         FROM EMP
         WHERE EMP_NO = 291;

    方法2 (次低效)

            DECLARE
             CURSOR C1 (E_NO NUMBER) IS
             SELECT EMP_NAME,SALARY,GRADE
    FROM EMP
             WHERE EMP_NO = E_NO;
         BEGIN
             OPEN C1(342);
             FETCH C1 INTO …,..,.. ;
                     OPEN C1(291);
            FETCH C1 INTO …,..,.. ;
              CLOSE C1;
           END;

    方法3 (高效)

         SELECT A.EMP_NAME , A.SALARY , A.GRADE,
                 B.EMP_NAME , B.SALARY , B.GRADE
         FROM EMP A,EMP B
         WHERE A.EMP_NO = 342
         AND   B.EMP_NO = 291;

    注意:
    在SQL*Plus , SQL*Forms和Pro*C中重新设置ARRAYSIZE参数, 可以增加每次数据库访问的检索数据量 ,建议值为200.

    重点关注4:使用DECODE函数来减少处理时间.重点关注
    使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.
    例如:

    SELECT COUNT(*), SUM(SAL)
    FROM EMP
    WHERE DEPT_NO = 20 AND ENAME LIKE ‘SMITH % ’;
    
    SELECT COUNT(*), SUM(SAL)
    FROM EMP
    WHERE DEPT_NO = 30 AND ENAME LIKE ‘SMITH % ’;

    你可以用DECODE函数高效地得到相同结果

    SELECT COUNT(DECODE(DEPT_NO, 0020, ’X’, NULL)) AS D0020_COUNT
        , COUNT(DECODE(DEPT_NO, 0030, ’X’, NULL)) AS D0030_COUNT
        , SUM(DECODE(DEPT_NO, 0020, SAL, NULL)) AS D0020_SAL
        , SUM(DECODE(DEPT_NO, 0030, SAL, NULL)) AS D0030_SAL
    FROM EMP
    WHERE ENAME LIKE ‘SMITH % ’;

    类似的,DECODE函数也可以运用于GROUP BYORDER BY子句中.

    重点关注5: 删除重复记录.重点关注

    最高效的删除重复记录方法 ( 因为使用了ROWID)

    DELETE FROM EMP E
    WHERE E.ROWID >(SELECT MIN(X.ROWID) FROM EMP X 
                    WHERE X.EMP_NO = E.EMP_NO);

    重点关注6: 用TRUNCATE替代DELETE.重点关注

    当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) 用来存放可以被恢复的信息. 如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况)
    而当运用TRUNCATE时, 回滚段不再存放任何可被恢复的信息.当命令运行后,数据不能被恢复.因此很少的资源被调用,执行时间也会很短.
    (译者按: TRUNCATE只在删除全表适用,TRUNCATE是DDL不是DML)

    重点关注7: 尽量多使用COMMIT.重点关注

    只要有可能,在程序中尽量多使用COMMIT, 这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少:

    COMMIT所释放的资源:

    a.回滚段上用于恢复数据的信息.
    b.被程序语句获得的锁
    c.redo log buffer 中的空间
    d.ORACLE为管理上述3种资源中的内部花费

    (译者按: 在使用COMMIT时必须要注意到事务的完整性,现实中效率和事务完整性往往是鱼和熊掌不可得兼)

    重点关注8:减少对表的查询.重点关注

    在含有子查询的SQL语句中,要特别注意减少对表的查询.

    例如:

    --低效
    SELECT TAB_NAME
    FROM TABLES
    WHERE TAB_NAME = (
            SELECT TAB_NAME
            FROM TAB_COLUMNS
            WHERE VERSION = 604
        )
        AND DB_VER = (
            SELECT DB_VER
            FROM TAB_COLUMNS
            WHERE VERSION = 604
        )
    --高效
    SELECT TAB_NAME
    FROM TABLES
    WHERE (TAB_NAME,DB_VER)
    = (SELECT TAB_NAME,DB_VER)
    FROM TAB_COLUMNS WHERE VERSION = 604)

    Update 多个Column 例子:

    --低效:
                UPDATE EMP
                SET EMP_CAT = (SELECT MAX(CATEGORY) FROM EMP_CATEGORIES),
                   SAL_RANGE = (SELECT MAX(SAL_RANGE) FROM EMP_CATEGORIES)
                WHERE EMP_DEPT = 0020;
    --高效:
                UPDATE EMP
                SET (EMP_CAT, SAL_RANGE)= (SELECT MAX(CATEGORY),MAX(SAL_RANGE) FROM EMP_CATEGORIES)
                WHERE EMP_DEPT = 0020;

    重点关注9:用EXISTS替代IN.重点关注

    在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率.

    --低效:
    SELECT *
    FROM EMP (基础表)
    WHERE EMPNO >0
    AND DEPTNO IN (SELECT DEPTNO
    FROM DEPT WHERE LOC = ‘MELB’)
    --高效:
    SELECT *
    FROM EMP (基础表)
    WHERE EMPNO >0
    AND EXISTS (SELECT ‘X’
    FROM DEPT
    WHERE DEPT.DEPTNO = EMP.DEPTNO
    AND LOC = ‘MELB’)

    (译者按: 相对来说,用NOT EXISTS替换NOT IN 将更显著地提高效率,下一节中将指出)

    重点关注10:用NOT EXISTS替代NOT IN .重点关注

    在子查询中,NOT IN子句将执行一个内部的排序和合并. 无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历). 为了避免使用NOT IN ,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS.
    例如:

    SELECTFROM EMP
    WHERE DEPT_NO NOT IN (SELECT DEPT_NO FROM DEPT WHERE DEPT_CAT=’A’);

    为了提高效率.改写为:

    --(方法一: 高效)
    SELECT ….
    FROM EMP A,DEPT B
    WHERE A.DEPT_NO = B.DEPT(+)
    AND B.DEPT_NO IS NULL
    AND B.DEPT_CAT(+) = ‘A’
    --(方法二: 最高效)
    SELECT ….
    FROM EMP E
    WHERE NOT EXISTS (SELECT ‘X’
                         FROM DEPT D
                         WHERE D.DEPT_NO = E.DEPT_NO 
                         AND DEPT_CAT = ‘A’);

    当然,最高效率的方法是有表关联.直接两表关系对联的速度是最快的!

    重点关注11:识别’低效执行’的SQL语句.重点关注

    用下列SQL工具找出低效SQL:

    --EXECUTIONS 所有子游标的执行这条语句次数
    --DISK_READS 所有子游标运行这条语句导致的读磁盘次数
    --BUFFER_GETS 所有子游标运行这条语句导致的读内存次数
    --Hit_radio 命中率
    --Reads_per_run 每次执行读写磁盘数
    SELECT EXECUTIONS , DISK_READS, BUFFER_GETS,
             ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio,
             ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run,SQL_TEXT
    FROM    V$SQLAREA
    WHERE   EXECUTIONS>0
    AND     BUFFER_GETS>0
    AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8
    ORDER BY 4 DESC;
    展开全文
  • 个求累加和程序的求解过程

    万次阅读 2012-02-29 09:32:02
    【题目】f=1-1/2!+1/3!-...+1/9! 【本文结构】  看题目,有点难度(相对而言,熟悉编程后,这只是一非常典型的问题)。将我带着大家把这问题分解一下,由易到难解出来。  我们要经历的过程是:  ...

    【题目】求f=1-1/2!+1/3!-...+1/9!


    【本文结构】

      看题目,有点难度(相对而言,熟悉编程后,这只是一个非常典型的问题)。将我带着大家把这个问题分解一下,由易到难解出来。

      我们要经历的过程是:

      (一)求f=1+2+...+9【很简单的问题】

      (二)求f=1-2+3-4+...+9【在(一)的基础上,学习如何一正一负地累加】

      (三)求f=1-1/2+1/3-1/4+...+1/9【在(二)的基础上,被加数成了自然数的倒数】

      (四)求f=1!-2!+3!-4!+...+9!【在(二)的基础上,被加数成了自然数的阶乘】

      (五)求f=1-1/2!+1/3!-...+1/9!【运用(三)和(四)的方法就能出来了】

      (六)用哪种循环语句其实并不是大事,本题以上的部分而言,for循环还是最好的

      (七)求f=1-1/2!+1/3!-1/4!+...,要求精度达到0.0000001【对题目的扩充,在数值求解时,常常并不限定累加的项数,而是用精度控制】

      如果这些题目对你目前已经不存在问题,体会这个化简的过程就可以关闭页面了。要学会这种办法,让自己由简而繁地工作。


    【相关练习题(加*者在文后给了参考例程)】

    • 对于任何正整数n,求1+n+n*n+n*n*n。
    • 不断从键盘中输入实数,边输入边累加,直到它们的和超过1000时为止。
    • 计算正整数n以内(包括n)的奇数之和及偶数之和。
    • 已知本金为a,年利率为x%,试求存入银行多少年后本、利和翻一番。(提示:用s表示本、利合计,循环要表达的是“当(s<2*a)时,增加1年,计算下一年末的本、利合计”)
    • 求任一长整数n的各位数字之和(提示:本题在每次循环中应该提取出某一位数并累加,即,先分离出个位累加,将n缩小10倍,重复操作直至n=0时为止。 )
    • 求任一长整数n的所有因子的之。(提示:循环中对所有可能成为该数因子的数进行考察,如果是因子,累加。 )
    • 在歌星大奖赛中,有10个评委为参赛的选手打分,分数为1~100分。选手最后得分为:去掉一个最高分和一个最低分后其余8个分数的平均值。请编写一个程序实现。

    • (*)一个百万富翁遇到一个陌生人,陌生人找他谈一个换钱的计划,该计划如下:我每天给你十万元,而你第一天只需给我一分钱,第二天我仍给你十万元,你给我两分钱,第三天我仍给你十万元,你给我四分钱,....,你每天给我的钱是前一天的两倍,直到满一个月(30天),百万富翁很高兴,欣然接受了这个契约。请编写程序计算30天后陌生人给了百万富翁多少钱,百万富翁给了陌生人多少钱?这个换钱计划对百万富翁是个划算的交易吗?
    • (*)现在北京有一套房子,价格200万,假设房价每年上涨10%,一个软件工程师每年固定能赚40万。如果他想买这套房子,不贷款,不涨工资,没有其他收入,每年不吃不喝不消费,那么他需要几年才能攒够钱买这套房子? (答案会让人很悲观。不过房价这样涨,是不正常的,总有泡泡吹破的一天。)

    【本文正文】

      (一)先做一个简单程序:f=1+2+...+9

      这太简单了!

    int main()
    {
      const int n=9;   //把9定义成常变量,这是个好办法,增强可读性、可维护性,见P30,讲过
      int i,f;   //本题求值后,f为整数,所以用int型。要根据情况选数据类型。i将用于控制循环,用int
      f=0;   //赋初值很重要,也可以定义的同时初始化。有同学算出了莫名其妙的和,因为没有赋初值
      for(i=1;i<=n;i++)
        f=f+i;         //请深刻理解for有运行机制,要习惯于这种思维
      cout<<f<<endl;
    }
    [小评论,为了解本题目求解过程的读者,直接跳到(二)]
      在这段程序中,for可以有各种其他写法,但惟有此为最佳:i控制了循环的次数(理解为何叫计数型循环)。我们将i称作为循环变量。在for(;;)中两个分号隔开的三部分中,分别只给循环变量赋初值、判断是否结束循环、循环变量调整,其余的任何操作统统放到别的地方去做。例如此处,为f赋初值放在循环前、累加的工作作为循环体。除些之外,别的写法,如
    for(f=0,i=1;i<=n;i++) f=f+i;

      或
    f=0,i=1;
    for(;i<=n;i++) f=f+i;
      或
    for(f=0,i=1;i<=n;f=f+i,i++);

      或

    f=0,i=1;
    for(;i<=n;)
    {
      f=f+i;
      i++;
    }
      之流的,还可以写出无数,都是不利于理解的写法。
      再欣赏一下正宗的for循环,想想前面的形式,那是什么东西!?最清晰、最好的写法是:

    f=0;
    for(i=1;i<=n;i++)
      f=f+i;

      (二)题目再变复杂些:f=1-2+3-4+...+9

    int main()
    {
      const int n=9;
      int i,f,sign=1;  //引入sign用于待加式子的符号变换
      f=0;   //赋初值很重要
      for(i=1;i<=n;i++)
      {                //因为循环体中将出现多条语句,加{}使之成为一条复合语句
        f=f+sign*i;
        sign=-sign;  //这个技术很重要,相比求幂,效率提高很多
      }
      cout<<f<<endl;
    }

      从这个例子中,我想强调:设计程序时,每一个变量的含义必须明确,不要试图让一个变量承担过多的角色。有些同学的变量用得很乱,碰巧得到正确的结果,有时还沾沾自喜,孰料其中存在大大的隐患。

      sign变量的名字也再次告诉我们,变量起名时,要尽量起有意义的名字,尤其其中几个变量间的关系微妙时。小程序中常用n、i、f之类的,其实并不是好习惯。想想dTax、fNetIncome,何等的清楚。


      (三)还再变复杂些:f=1-1/2+1/3-1/4+...+1/9。

    int main()
    {
      const int n=9;
      int i,sign=1;
      double f; //为什么换类型了?算下来f是小数,还用整型那不找错吗?
      f=0;
      for(i=1;i<=n;i++)
      {
        f=f+sign*double(1)/i;  //这儿涉及类型转换,下面将深入讨论
        sign=-sign;  //sign只用作控制符号,不作他用,欣赏一下
      }
      cout<<f<<endl;
    }
    

      关于类型,因为i为int型,如果直接1/i结果为int型,因为i≥1,从第2次循环开始(i=2),f就一直累加0了,多么可怕的一个潜在Bug。也可以写作1/double(i),但不能是double(1/i),已经求得商为0了,再double有何用,无法起死回生了。从语句整体,写成f=f+sign/double(i);更好。

      在同学学愿意将i用作double型或float型,这样f=f+sign*1/i;或f=f+sign/i;都行。但是i是用于计数的(顺便做了除数而已)这个含义将被削弱。我个人还是不赞同这样做,尽管需要进行强制类型转换。


      (四)在(二)的基础上再做次复杂化:f=1!-2!+3!-4!+...+9!
      增加一个变量a用于表示等待累加的阶乘值,显然,在累加3!时,上一循环计算得到的阶乘a为2!,a*3即是要加的3!。
    int main()
    {
      const int n=9;
      int i,f,a,sign=1;  //引入sign用于待加式子的符号变换
      f=0;   //累加和的初值取0
      a=1;   //累乘积的初值取1 
      for(i=1;i<=n;i++)
      {                
        a=a*i;
        f=f+sign*a;   //将阶乘加上去,不要试图将求幂也写到一个语句中,那样的程序没法读了
        sign=-sign;  
      }
      cout<<f<<endl;
    }

      (五)到此应该知道:将(三)和(四)结合起来就是我们要的结果了!
      计算:f=1-1/2!+1/3!-...+1/9!
    #include <iostream>
    using namespace std;
    int main()
    {
      const int n=9;
      int i,a,sign=1;
      double f; 
      f=0;
      a=1;  //再说一点,很多同学将这两个语句写在一行,没错,但不好
      for(i=1;i<=n;i++)
      {
        a=a*i;
        f=f+sign*double(1)/a;  
        sign=-sign;  
      }
      cout<<f<<endl;
    }
    

      (六)用其他的循环语句完成求解
      *********************用while循环实现************************
      给出循环:
    for(i=1;i<=n;i++)
        f=f+i;
      对应的while循环是:
    i=1;
    while(i<=n)
    {
      f=f+i;
      i++;
    }
      仍然是一个漂亮的计数!只不过将要做的事情在合适的位置上安排好罢了。
      用while实现计算f=1-1/2!+1/3!-...+1/9!的程序是

    #include <iostream>
    using namespace std;
    int main()
    {
      const int n=9;
      int i,a,sign=1;
      double f; 
      f=0;
      a=1;
      i=1; //对应原先for循环中的<表达式1>,—— for(i=1;i<=n;i++)
      while(i<=n)  //循环条件是原for循环中的<表达式2>,—— for(i=1;i<=n;i++)
      {
        a=a*i;
        f=f+sign*double(1)/a;  
        sign=-sign;
        i++;     //不要漏下原for循环中的<表达式3>,—— for(i=1;i<=n;i++)  
      }
      cout<<f<<endl;
    }


      *********************用do-while循环实现************************
      给出循环:
    for(i=1;i<=n;i++)
      f=f+i;
      如果能够保证循环体至少能执行1次,对应的do-while循环是:
    i=1;
    do
    {
      f=f+i;
      i++;
    }
    while(i<=n);
      换汤不换药,关键在于,对这种循环的运行过程要了然于胸。
      for循环和while循环的循环体允许一次都不执行,如果循环条件一开始就不满足。而do-while循环的循环体则最少执行一行。为此,有些问题用do-while写时就有其特点了,此处不表。
      用do-while实现计算f=1-1/2!+1/3!-...+1/9!的程序是:
    #include <iostream>
    using namespace std;
    int main()
    {
      const int n=9;
      int i,a,sign=1;
      double f; 
      f=0;
      a=1;
      i=1; //循环的初始条件
      do  
      {
        a=a*i;
        f=f+sign*double(1)/a;  
        sign=-sign;
        i++;          //循环变量的变化写在循环体内
      }while(i<=n);   //确定在何条件下循环可以继续
      cout<<f<<endl;
    }

      (七)题目的扩充,求f=1-1/2!+1/3!-1/4!+...,要求精度达到0.0000001
      在数值求解时,常常并不限定累加的项数,而是用精度控制。
      上述题目的意思是:利用循环累加9次,或者说,累加,直到加了第9项。
      现在的问题是:需要加几次不知道,但最后一项小于0.0000001后就不再加了。或者说,累加,直到要加的项小于0.0000001。
      当累加的项数不确定时,建议直接用while的思维考虑这个问题。
      用伪代码表示这个思路:
    累加的项item初值为1;
    while(item > 0.0000001)
    	执行累加任务;
      读者可以再细化算法。对应的C++程序是:
    #include <iostream>
    using namespace std;
    int main()
    {
      const int n=9;
      int i,a,sign=1;
      double f,item; 
      f=0;   //累加和
      a=1;   //阶乘
      i=1;   //第几项?
      item = 1;  //要加的项
      while(item > 0.0000001)  
      {
        item = double(1)/a; 
    	f=f+sign*item;  
        a=a*i; 
    	sign=-sign;
        i++;      
      }
      cout<<f<<endl;
    }
    

    【部分练习参考例程】
    一个百万富翁遇到一个陌生人,陌生人找他谈一个换钱的计划,该计划如下:我每天给你十万元,而你第一天只需给我一分钱,第二天我仍给你十万元,你给我两分钱,第三天我仍给你十万元,你给我四分钱,....,你每天给我的钱是前一天的两倍,直到满一个月(30天),百万富翁很高兴,欣然接受了这个契约。请编写程序计算30天后陌生人给了百万富翁多少钱,百万富翁给了陌生人多少钱?这个换钱计划对百万富翁是个划算的交易吗?
    #include<iostream>
    using namespace std;
    int main()
    {
     int days=1;
     double m2fs=0, f2ms=0; //总额,m2f--陌生人to富翁
     double m2f=100000, f2m=0.01; //每天应付数额
     while(days<=30)
     {
      m2fs=m2fs+m2f;
      f2ms=f2ms+f2m;
      cout<<"第"<<days<<"天,陌生人给百万富翁"<<m2fs<<"元,百万富翁给陌生人"<<f2ms<<"元。"<<endl;
      f2m*=2;
      days++;
     }
     if(m2fs>f2ms)
      cout<<"陌生人吃亏。"<<endl;
     else
      cout<<"百万富翁吃亏。"<<endl;
     return 0;
    }
    建议:此程序中变量的取名可以借鉴一下。

    题目:现在北京有一套房子,价格200万,假设房价每年上涨10%,一个软件工程师每年固定能赚40万。如果他想买这套房子,不贷款,不涨工资,没有其他收入,每年不吃不喝不消费,那么他需要几年才能攒够钱买这套房子? 
    #include <iostream>  
    using namespace std;  
    int main()  
    { 
       double house_price=200, money = 40;
       int year=1;
       const double rate = 0.1;
       const int salary = 40;
       while(money < house_price)
       {
    	   cout<<year<<" "<<money<<"  "<<house_price<<endl;
    	   ++year;
    	   house_price*=(1+rate);
    	   money+=salary;
       }
      cout<<endl;
      return 0;
    }
    思考:(1)程序会进入列限循环直至出错(这是求解结果让人沮丧的事情),如何让程序能在合适的时候停下来?(2)如果 rate = 5%,结果会如何?
     
    
    展开全文
  • 2. 与等价划分的区别1) 边界分析不是从某等价类中随便挑一作为代表,而是使这等价类的每边界都要作为测试条件。2) 边界分析不仅考虑输入条件,还要考虑输出空间产生的测试情况。3. 边界分析方法的考

    一.方法简介

    1. 定义:边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法。通常边界值分析法是作为对等价类划分法的补充,这种情况下,其测试用例来自等价类的边界。

    2. 与等价划分的区别

    1) 边界值分析不是从某等价类中随便挑一个作为代表,而是使这个等价类的每个边界都要作为测试条件。

    2) 边界值分析不仅考虑输入条件,还要考虑输出空间产生的测试情况。

    3. 边界值分析方法的考虑:

    长期的测试工作经验告诉我们,大量的错误是发生在输入或输出范围的边界上,而不是发生在输入输出范围的内部。因此针对各种边界情况设计测试用例,可以查出更多的错误。

    使用边界值分析方法设计测试用例,首先应确定边界情况。通常输入和输出等价类的边界,就是应着重测试的边界情况。应当选取正好等于,刚刚大于或刚刚小于边界的值作为测试数据,而不是选取等价类中的典型值或任意值作为测试数据。

    4. 常见的边界值

    1) 对16-bit 的整数而言 32767 和 -32768 是边界

    2) 屏幕上光标在最左上、最右下位置

    3) 报表的第一行和最后一行

    4) 数组元素的第一个和最后一个

    5) 循环的第 0 次、第 1 次和倒数第 2 次、最后一次

    5. 边界值分析

    1) 边界值分析使用与等价类划分法相同的划分,只是边界值分析假定错误更多地存在于划分的边界上,因此在等价类的边界上以及两侧的情况设计测试用例。

    例:测试计算平方根的函数

    --输入:实数

    --输出:实数

    --规格说明:当输入一个0或比0大的数的时候,返回其正平方根;当输入一个小于0的数时,显示错误信息"平方根非法-输入值小于0"并返回0;库函数Print-Line可以用来输出错误信息。

    2) 等价类划分:

    I.可以考虑作出如下划分:

    a、输入 (i)<0 和 (ii)>=0

    b、输出 (a)>=0 和 (b) Error

    II.测试用例有两个:

    a、输入4,输出2。对应于 (ii) 和 (a) 。

    b、输入-10,输出0和错误提示。对应于 (i) 和 (b) 。

    3) 边界值分析:

    划分(ii)的边界为0和最大正实数;划分(i)的边界为最小负实数和0。由此得到以下测试用例:

    a、输入 {最小负实数}

    b、输入 {绝对值很小的负数}

    c、输入 0

    d、输入 {绝对值很小的正数}

    e、输入 {最大正实数}

    4) 通常情况下,软件测试所包含的边界检验有几种类型:数字、字符、位置、重量、大小、速度、方位、尺寸、空间等。

    5) 相应地,以上类型的边界值应该在:最大/最小、首位/末位、上/下、最快/最慢、最高/最低、 最短/最长、 空/满等情况下。

    6) 利用边界值作为测试数据

      边界值测试用例的设计思路
    字符起始-1个字符/结束+1个字符假设一个文本输入区域允许输入1个到255个 字符,输入1个和255个字符作为有效等价类;输入0个和256个字符作为无效等价类,这几个数值都属于边界条件值。
    数值最小值-1/最大值+1假设某软件的数据输入域要求输入5位的数据值,可以使用10000作为最小值、99999作为最大值;然后使用刚好小于5位和大于5位的 数值来作为边界条件。
    空间小于空余空间一点/大于满空间一点例如在用U盘存储数据时,使用比剩余磁盘空间大一点(几KB)的文件作为边界条件。

    7) 内部边界值分析:

    在多数情况下,边界值条件是基于应用程序的功能设计而需要考虑的因素,可以从软件的规格说明或常识中得到,也是最终用户可以很容易发现问题的。然 而,在测试用例设计过程中,某些边界值条件是不需要呈现给用户的,或者说用户是很难注意到的,但同时确实属于检验范畴内的边界条件,称为内部边界值条件或 子边界值条件。

    内部边界值条件主要有下面几种:

    a) 数值的边界值检验:计算机是基于二进制进行工作的,因此,软件的任何数值运算都有一定的范围限制。

      范围或值
    位(bit)0 或 1
    字节(byte)0 ~ 255
    字(word)0~65535(单字)或 0~4294967295(双字)
    千(K)1024
    兆(M)1048576
    吉(G)1073741824

    b) 字符的边界值检验:在计算机软件中,字符也是很重要的表示元素,其中ASCII和Unicode是常见的编码方式。下表中列出了一些常用字符对应的ASCII码值。

      字符ASCII码值字符ASCII码值
    空 (null)0A65
    空格 (space)32a97
    斜杠 ( / )47Z90
    048z122
    冒号 ( : )58单引号 ( ‘ )96
    @64  

    c) 其它边界值检验

    6. 基于边界值分析方法选择测试用例的原则

    1) 如果输入条件规定了值的范围,则应取刚达到这个范围的边界的值,以及刚刚超越这个范围边界的值作为测试输入数据。

    例如,如果程序的规格说明中规定:"重量在10公斤至50公斤范围内的邮件,其邮费计算公式为……"。作为测试用例,我们应取10及50,还应取10.01,49.99,9.99及50.01等。

    2) 如果输入条件规定了值的个数,则用最大个数,最小个数,比最小个数少一,比最大个数多一的数作为测试数据。 比如,一个输入文件应包括1~255个记录,则测试用例可取1和255,还应取0及256等。

    3) 将规则1)和2)应用于输出条件,即设计测试用例使输出值达到边界值及其左右的值。

    例如,某程序的规格说明要求计算出"每月保险金扣除额为0至1165.25元",其测试用例可取0.00及1165.24、还可取一0.01及1165.26等。

    再如一程序属于情报检索系统,要求每次"最少显示1条、最多显示4条情报摘要",这时我们应考虑的测试用例包括1和4,还应包括0和5等。

    4) 如果程序的规格说明给出的输入域或输出域是有序集合,则应选取集合的第一个元素和最后一个元素作为测试用例。

    5) 如果程序中使用了一个内部数据结构,则应当选择这个内部数据结构的边界上的值作为测试用例。

    6) 分析规格说明,找出其它可能的边界条件。

    二.实战演习

    1.现有一个学生标准化考试批阅试卷,产生成绩报告的程序。其规格说明如下:程序的输入文件由一些有80个字符的记录组成,如右图所示,所有记录分为3组:

    ① 标题:这一组只有一个记录,其内容为输出成绩报告的名字。

    ② 试卷各题标准答案记录:每个记录均在第80个字符处标以数字"2"。该组的第一个记录的第1至第3个字符为题目编号(取值为1一999)。第10至第59 个字符给出第1至第50题的答案(每个合法字符表示一个答案)。该组的第2,第3……个记录相应为第51至第100,第101至第150,…题的答案。

    ③ 每个学生的答卷描述:该组中每个记录的第80个字符均为数字"3"。每个学生的答卷在若干个记录中给出。如甲的首记录第1至第9字符给出学生姓名及学号, 第10至第59字符列出的是甲所做的第1至第50题的答案。若试题数超过50,则第2,第3……纪录分别给出他的第51至第100,第101至第 150……题的解答。然后是学生乙的答卷记录。

    ④ 学生人数不超过200,试题数不超过999。

    ⑤ 程序的输出有4个报告:

    a) 按学号排列的成绩单,列出每个学生的成绩、名次。

    b) 按学生成绩排序的成绩单。

    c) 平均分数及标准偏差的报告。

    d) 试题分析报告。按试题号排序,列出各题学生答对的百分比。

    解答:分别考虑输入条件和输出条件,以及边界条件。给出下表所示的输入条件及相应的测试用例。

    输出条件及相应的测试用例表。

    2.三角形问题的边界值分析测试用例

    在三角形问题描述中,除了要求边长是整数外,没有给出其它的限制条件。在此,我们将三角形每边边长的取范围值设值为[1, 100] 。 

    测试用例

    a

    b

    c

    预期输出

    Test1

    Test2

    Test3

    Test4

    Test5

    60

    60

    60

    50

    50

    60

    60

    60

    50

    50

    1

    2

    60

    99

    100

    等腰三角形

    等腰三角形

    等边三角形

    等腰三角形

    非三角形

    Test6

    Test7

    Test8

    Test9

    60

    60

    50

    50

    1

    2

    99

    100

    60

    60

    50

    50

    等腰三角形

    等腰三角形

    等腰三角形

    非三角形

    Test10

    Test11

    Test12

    Test13

    1

    2

    99

    100

    60

    60

    50

    50

    60

    60

    50

    50

    等腰三角形

    等腰三角形

    等腰三角形

    非三角形

    3.NextDate函数的边界值分析测试用例

    NextDate是一个有三个变量(月份、日期、和年)的函数,函数返回输入日期后面的那个日期。变量都具有整数值,且满足以下条件:

    C1 1<=月份<=12
    C2 1<=日期<=31
    C3 1912<=年<=2050

    在NextDate函数中,隐含规定了变量mouth和变量day的取值范围为1≤mouth≤12和1≤day≤31,并设定变量year的取值范围为1912≤year≤2050 。  

    测试用例

    mouth

    day

    year

    预期输出

    Test1

    Test2

    Test3

    Test4

    Test5

    Test6

    Test7

    6

    6

    6

    6

    6

    6

    6

    15

    15

    15

    15

    15

    15

    15

    1911

    1912

    1913

    1975

    2049

    2050

    2051

    year超出[1912,2050]

    1912.6.16

    1913.6.16

    1975.6.16

    2049.6.16

    2050.6.16

    year超出[1912,2050]

    Test8

    Test9

    Test10

    Test11

    Test12

    Test13

    6

    6

    6

    6

    6

    6

    -1

    1

    2

    30

    31

    32

    2001

    2001

    2001

    2001

    2001

    2001

    day超出[1…31]

    2001.6.2

    2001.6.3

    2001.7.1

    输入日期超界

    day超出[1…31]

    Test14

    Test15

    Test16

    Test17

    Test18

    Test19

    -1

    1

    2

    11

    12

    13

    15

    15

    15

    15

    15

    15

    2001

    2001

    2001

    2001

    2001

    2001

    Mouth超出[1…12]

    2001.1.16

    2001.2.16

    2001.11.16

    2001.12.16

    Mouth超出[1…12]

    通过分析前两个测试用例表,就会发现这些测试用例是不充分的,而且存在冗余。
    三角形问题上没有考虑两边之和大于第三边。
    在NextDate函数中没有考虑2月和闰年的问题。

    如果被测程序是多个独立变量的函数,则很适合采用边界值分析。

    等价类测试

    动机   :希望进行完备的测试 希望避免冗余
    等价类的划分:

    根据等价关系对输入或输出数据的集合进行划分
    将集合划分为互不相交的子集(无冗余性)
    这些子集的并是整个集合(完备性)
    等价类的划分的几个依据:
    1. 按照区间划分
    2. 按照数值划分
    3. 按照数值集合划分
    4. 按照限制条件或规格划分
    弱一般等价类测试
    强一般等价类测试
    弱健壮等价类测试
    强健壮等价类测试

    “弱” 是指遵循单缺陷原则
    “强” 是指遵循多缺陷原则
    “健壮” 是指考虑无效值
    弱一般等价类 考虑单缺陷假设
    测试用例使用每个等价类中的一个值
    设两变量x1和x2函数有以下边界和等价区间:
    a<=x1<=d,区间为:[a,b),[b,c),[c,d]
    e<=x2<=g,区间为:[e,f),[f,g)
    强一般等价类测试   考虑多缺陷假设
    测试用例集合为等价类笛卡儿积
    设两变量x1和x2函数有以下边界和等价区间:
    a<=x1<=d,区间为:[a,b),[b,c),[c,d]
    e<=x2<=g,区间为:[e,f),[f,g)
    弱健壮等价类测试 考虑单缺陷假设、无效值
    用例标识
    对于有效输入,使用每个有效类的一个值
    对于无效输入,使用一个无效值,并保持其余的值都有效的
    强健壮等价类测试   考虑多缺陷假设、无效值
    用例标识
    从所有等价类(包括若干无效等价类)笛卡儿乘积中选取
    案例分析-三角形问题的等价类测试用例
    使用输出确定等价类
    R1={等边三角形}
    R2={等腰三角形}
    R3={不等边三角形}
    R4={不构成三角形}
    弱一般等价类测试用例(强一般等价类)
    测试用例 a b c 预期输出
    WN1 5 5 5 等边三角形
    WN2 2 2 3 等腰三角形
    WN3 3 4 5 不等边三角形
    WN4 4 1 2 不构成三角形
    弱健壮等价类测试用例(考虑a,b,c的无效值)

    测试用例 a b c 预期输出
    WR1 -1 5 5 a值不在范围内
    WR2 5 -1 5 b值不在范围内
    WR3 5 5 -1 c值不在范围内
    WR4 201 5 5 a值不在范围内
    WR5 5 201 5 b值不在范围内
    WR6 5 5 201 c值不在范围内

    强健壮等价类测试的用例
    测试用例 a b c 预期输出
    SR1 -1 5 5 a值不在范围内
    SR2 5 -1 5 b值不在范围内
    SR3 5 5 -1 c值不在范围内
    SR4 -1 -1 5 a,b值不在范围内
    SR5 5 -1 -1 b,c值不在范围内
    SR6 -1 5 -1 a,c值不在范围内
    SR7 -1 -1 -1 a,b,c值不在范围内
    SR8 201 5 5 a值不在范围内
    SR9 5 201 5 b值不在范围内
    SR10 5 5 201 c值不在范围内
    SR11 201 201 5 a,b值不在范围内
    SR12 5 201 201 b,c值不在范围内
    SR13 201 5 201 a,c值不在范围内
    SR14 201 201 201 a,b,c值不在范围内

    案例分析-NextDate函数的等价类测试用例
    确定等价类
    M1={月份:每月有30天}
    M2={月份:每月有31天}
    M3={月份:此月是2月}
    D1={日期:1<=日期<=28}
    D2={日期:日期=29}
    D3={日期:日期=30}
    D4={日期:日期=31}
    Y1={年:年是闰年}
    Y2={年:年是平年}
    弱一般等价类测试用例应该有多少?
    强一般等价类测试用例应该有?
    强健壮等价类测试用例?
    等价类测试用例
    弱一般等价类测试用例应该有4个
    强一般等价类测试用例应该有
       3个(月份类)x 4个(日期类)x 2(年类)= 24个
    强健壮等价类测试用例
    对每个变量加上2个无效类
    测试用例数为:5 x 6 x 4 = 120个
    弱一般等价类:遵循单缺陷原则,要求用例覆盖每一个变量的一种取值即可,取值为有效值。     强一般等价类:遵循多缺陷原则,要求用例覆盖每个变量的每种取值之间的迪卡尔乘积,即所有变量所有取值的所有组合,取值为有效值。     弱健壮等价类:在弱一般等价类的基础上,增加取值为无效值的情况。     强健壮等价类:在强一般等价类的基础上,增加取值为无效值的情况。

    基于决策表的测试
    也称判定表,是分析和表达多逻辑条件下执行不同操作的情况的工具
    条件桩   条件项
    动作桩 动作项
    条件桩:列出了问题的所有条件。通常认为列出的条件的次序无关紧要。
    动作桩:列出了问题规定可能采取的操作。这些操作的排列顺序没有约束。
    条件项:列出针对它左列条件的取值。在所有可能情况下的真假值。
    动作项:列出在条件项的各种取值情况下应该采取的动作。
    规则:任何一个条件组合的特定取值及其相应要执行的操作称为规则。
    将具有相同动作,并且其条件项之间存在着极为相似关系的两条或多条规则合并为一条规则
    1 列出条件桩C1:a<b+c?C2:b<a+c?C3:C<a+b?C4:a=b?C5:a=c?C6:b=c?
    2 列出动作桩 非三角形 不等边三角形 等腰三角形 等边三角形 不可能
    C1:a<b+c? F T T T T T T T T T T
    C2:b<a+c? - F T T T T T T T T T
    C3:C<a+b? - - F T T T T T T T T
    C4:a=b? - - - T T T T F F F F
    C5:a=c? - - - T T F F T T F F
    C6:b=c? - - - T F T F T F T F
    A1:非三角形 √ √ √        
    A2:不等边三角形            √
    A3:等腰三角形        √   √ √
    A4:等边三角形     √       
    A5:不可能      √ √   √   
    用例ID a b c 预期输出
    DT1 4 1 2 非三角形
    DT2 1 4 2 非三角形
    DT3 1 2 4 非三角形
    DT4 5 5 5 等边三角形
    DT5 ? ? ? 不可能
    DT6 ? ? ? 不可能
    DT7 2 2 3 等腰三角形
    DT8 ? ? ? 不可能
    DT9 2 3 2 等腰三角形
    DT10 3 2 2 等腰三角形
    DT11 3 4 5 不等边三角形

    用例ID 月份 日期 年 预期输出
    1--3 4 12 2001 2001年4月12日
    4 4 30 2001 2001年5月1日
    5 4 31 2001 不可能
    6--9 1 15 2001 2001年1月16日
    10 1 31 2001 2001年2月1日
    11-14 12 15 2001 2001年12月16日
    15 12 31 2001 2002年1月1日
    16 2 15 2001 2001年2月16日
    17 2 28 2004 2004年2月29日
    18 2 28 2001 2001年3月1日
    19 2 29 2004 2005年3月1日
    20 2 29 2001 不可能
    21,22 2 30 2001 不可能
    边界值分析
    基于定义域,不识别数据或逻辑关系
    很容易自动化实现
    设计工作量小
    生成的测试用例数比较多
    测试用例执行时间长
    等价类技术
    考虑数据依赖关系
    标识等价类时需要更多的判断和技巧
    等价类标识出以后的处理也是机械的
    设计工作量和测试用例数属中等
    决策表技术
    又要考虑数据的逻辑依赖关系
    所得测试用例可以是完备的
    测试数量在一定意义上讲是最少的
    需要通过多次迭代
    设计工作量很大

    综合案例
    保险金计算程序
    保险金=500 x 年龄系数 – 安全驾驶折扣
    安全驾驶折扣是投保人驾驶执照上当前点数的函数
    年龄系数是投保人年龄的函数
    若点数低于等于与年龄有关的点数门限,则给予安全驾驶折扣
    程序输入:年龄,点数
    驾驶人年龄范围为16-100岁
    点数范围为0-12
    输出:保险金
    年龄系数和安全驾驶折扣计算表
    年龄范围 年龄系数 门限点数 安全驾驶折扣
    16<=年龄<25 2.8 1 50
    25 < =年龄< 35 1.8 3 50
    35 < =年龄< 45 1.0 5 100
    45 < =年龄< 60 0.8 7 150
    60 < =年龄<= 100 1.5 5 200
    变量 最小值 略大于最小值 正常值 略小于最大值 最大值
    年龄 16 17 54 99 100
    点数 0 1 6 11 12
    变量 最小值 略大于最小值 正常值 略小于最大值 最大值
    年龄 16 17 20 24 -
    年龄 25 26 30 34 -
    年龄 35 36 40 44 -
    年龄 45 46 53 59 -
    年龄 60 61 75 99 100
    点数 0 - - - 1
    点数 2 - - - 3
    点数 4 - - - 5
    点数 6 - - - 7
    点数 8 9 10 11 12
    点数边界值共有13个,年龄边界值共有21个
    笛卡儿乘积(最坏情况边界值测试用例)共有273个元素,存在严重冗余
    年龄等价类集合
    A1={16<=年龄<25}
    A2={25<=年龄<35}
    A3={35<=年龄<45}
    A4={45<=年龄<60}
    A5={60<=年龄<=100}
    点数等价类集合
    P1={点数=0,1}
    P2={点数=2,3}
    P3={点数=4,5}
    P4={点数=6,7}
    P5={点数=8,9,10,11,12}
    保险金程序的强等价类测试用例
    用例ID 年龄 点数
    1 18 0
    2 18 2
    3 18 4
    4 18 6
    5 18 10
    6 30 0
    7 30 2
    8 30 4
    9 30 6
    10 30 10
    11 40 0
    12 40 2
    13 40 4
    14 40 6
    15 40 10
    16 50 0
    17 50 2
    18 50 4
    19 50 6
    20 50 10
    21 80 0
    22 80 2
    23 80 4
    24 80 6
    25 80 10
    决策表方法
    年龄 16-25 16-25 25-35 25-35 35-45 35-45
    点数 0-1 2-12 0-3 4-12 0-5 6-12
    年龄系数 2.8 2.8 1.8 1.8 1 1
    安全驾驶折扣 50 0 50 0 100 0
    年龄 45-60 45-60 60-100 60-100
    点数 0-7 8-12 0-5 6-12
    年龄系数 0.8 0.8 1.5 1.5
    安全驾驶折扣 150 0 200 0

    保险金程序的决策表测试用例
    用例ID 年龄 点数
    1 18 0
    2 18 2
    3 30 0
    4 30 4
    5 40 5
    6 40 6
    7 50 7
    8 50 8
    9 80 5
    10 80 6

    展开全文
  •  主要将两个或者更多个查询的结果组合为单个结果集,该结果集包含联合查询中的全部查询的全部行   select 仓库号 from 仓库 where 城市='北京' union select 仓库号 from 职工 where 工资>2000 select ...
     
    

    1:

    use db_sqlserver2
    select 姓名, 工资, 面积, 金额, (工资+金额/1000) as 实发工资 from 职工,仓库, 订购单 
       where 职工.职工号=订购单.职工号 and 职工.仓库号=仓库.仓库号



    2:

    select 姓名,工资,金额 from 职工,订购单 where 姓名 like '%平%' and 职工.职工号 = 订购单.职工号 order by 工资 desc
       

    3:

    select 姓名,工资,金额 from 职工,订购单 where 姓名 like '%平%' and 职工.职工号 = 订购单.职工号 order by 工资 desc, 金额 desc
    
       



    4:

    select 姓名, 工资, 城市, (select AVG(工资) from 职工) as 平均工资 , (工资-(select AVG(工资) from 职工)) as 与平均工资之差
    from 职工, 仓库 where 仓库.仓库号=职工.仓库号



    5:带保存功能的多表连接查询

        在SQL语句中,利用into语句可以把查询到的结果保存成一张新表,然后再对新表进行数据信息查询。

        

    select 仓库.仓库号, 城市, 面积, 姓名, 工资, 金额 into 多表连接产生的新表 from 仓库, 职工, 订购单 
    where 仓库.仓库号=职工.仓库号 and 职工.职工号=订购单.职工号

    select * from 多表连接产生的新表



    //查看不同仓库中的所有职工的仓库号、平均销售金额、最大销售金额、最小销售金额、最大销售金额与最小销售金额之差的信息

    select 仓库号, AVG(金额) as 平均销售金额, MAX(金额) as 最大销售金额, MIN(金额) as 最小销售金额, 
    (MAX(金额) - MIN(金额)) as 最大金额与最小金额之差 from 多表连接产生的新表 group by 仓库号;



    可以把分组查询结果再生成一张新表

    select 仓库号, AVG(金额) as 平均销售金额, MAX(金额) as 最大销售金额, MIN(金额) as 最小销售金额, 
    (MAX(金额) - MIN(金额)) as 最大金额与最小金额之差 into 分组查询产生的新表
     from 多表连接产生的新表 group by 仓库号;
     
     select * from 分组查询产生的新表


    6: 内连接查询(inner join)

        使用比较运算符对表之间的某些数据进行比较,并列出这些表中与连接条件相匹配的数据行。

        

      select 姓名, 城市 from 仓库 inner join 职工 on 职工.仓库号=仓库.仓库号


       多表的内连接查询

       

    select 城市,面积, 姓名, 工资, 金额 from 仓库   
      inner join 职工 on 职工.仓库号=仓库.仓库号
      inner join 订购单 on 职工.职工号=订购单.职工号
      and 工资>1800 and 面积<1000 and 金额 != 16600
       


    7:左连接查询(left join)

          除满足连接条件的记录显示外,第一张表中不满足条件的记录也显示在结果集中。

        

    select 姓名, 城市 from 仓库 
       left join 职工 on 职工.仓库号=仓库.仓库号 and 城市 is not null and 姓名 like '%王%'


    select 城市, 面积, 姓名, 工资, 金额 from 仓库 
       left join 职工 on 职工.仓库号 = 仓库.仓库号
       left join 订购单 on 职工.职工号=订购单.职工号
       and 工资>1800 and 面积<1000 and 金额!=16600
       


      在第一个left join左连接中,第一张表是仓库表,第二张表是职工表,在第二个left join左连接中,第一张表是职工表,第二张表是订购单表


    8:右连接查询

          除满足连接条件的记录显示外,第二张表中不满足条件的记录也显示在查询结果集中

         

    select 姓名, 城市 from 仓库 
    right join 职工 on 职工.仓库号=仓库.仓库号 where 城市 is not null and 姓名 like '%王%'

      

    select 城市, 面积, 姓名, 工资, 金额 from 仓库 
       right join 职工 on 职工.仓库号=仓库.仓库号
       right join 订购单 on 职工.职工号=订购单.职工号
       and 工资>1500 and 面积<1000 and 金额!=16600



    select 城市, 面积, 姓名, 工资, 金额 from 仓库 
       right join 职工 on 职工.仓库号=仓库.仓库号
       right join 订购单 on 职工.职工号=订购单.职工号
       where 工资>1500 and 面积<1000 and 金额!=16600
    把and关键字换为where关键字后的效果图,会发现那些无用的数据没有了

    


    9:全连接查询

        除满足连接条件的记录显示外,两张表中的不能满足条件的记录也显示在查询结果集中

        

    select 姓名,城市 from 仓库 full join 职工 on 职工.仓库号=仓库.仓库号 and 城市 is not null and
    姓名 like '%王%';




    集合的交、并、差运算查询

    为了进行并、交、差运算,要求运算的两个查询结果具有相同的字段个数,并且对应的字段的值要出自同一个值域,即具有相同的数据类型和取值范围

     10:并运算(union)

             主要将两个或者更多个查询的结果组合为单个结果集,该结果集包含联合查询中的全部查询的全部行

            

    select 仓库号 from 仓库 where 城市='北京'
    union
    select 仓库号 from 职工 where 工资>2000

    select 仓库号 from 仓库 where 城市='北京'
    union
    select 仓库号 from 职工 where 工资>2000
    
    select distinct 仓库.仓库号 from 仓库, 职工 where 仓库.仓库号=职工.仓库号 and (城市='北京' or 工资>2000)
     
    


    使用union all 保留重复行
    select 仓库号 from 仓库 where 城市='北京'
    union all
    select 仓库号 from 职工 where 工资>2000
    


    11:交运算(intersect)

      可以将两个select语句的查询结果通过交运算合并成一个查询结果

       

    select 仓库号 from 仓库 where 城市='北京'
    intersect
    select 仓库号 from 职工 where 工资>2000

    select distinct 仓库.仓库号 from 仓库, 职工 where 城市='北京' and 仓库.仓库号=职工.仓库号 and 工资>2000




    12:差运算(except)

         可以计算两个select查询结果之间的数据差,即返回在一个查询结果中存在,但在另一个查询结果中不存在的所有行。

        

    select 仓库号 from 仓库 where 城市='北京' 
    except 
    select 仓库号 from 职工 where 工资>2900

    select 仓库号 from 仓库 where 城市='北京' and 仓库号 not in(select 仓库号 from 职工 where 工资>2900)
    







    展开全文
  • Select之多表查询

    千次阅读 2018-06-03 18:34:45
    我们用一简单的公司管理系统,有三张表EMP ,DEPT,SALGRADE来演示如何进行多表查询。 内容如下: 创建部门 drop table if exists dept; create table if not exists dept ( deptno INT(2) ...
  • 真实地去设计优化单结构以及讲述多表设计基本原则(结合真实的生产环境的取舍来讲述)。 文章结构:(1)单设计与优化;(2)基于单设计的多表设计原则(含拆分原则);(均以实际生产开发环境下的环境为...
  • 通过连接可以建立多查询,多查询的数据可以来自多个表,但是之间必须有适当的连接条件。为了从多张表中查询,必须识别连接多张表的公共列。一般是在WHERE子句中用比较运算符指明连接的条件。   两个连接有...
  • Oracle 多表查询,子查询

    千次阅读 2011-10-21 13:46:23
    通过连接可以建立多查询,多查询的数据可以来自多个表,但是之间必须有适当的连接条件。为了从多张表中查询,必须识别连接多张表的公共列。一般是在WHERE子句中用比较运算符指明连接的条件。   两个连接...
  • SQL语言多表查询、分组统计、子查询、数据的更新操作、事务处理3.1、多表查询3.1.1、基本语法但是在多表查询之前首先必须处理一问题:例如:现在出雇员中的总记录数(14条记录)SELECT COUNT(*) FROM emp ;...
  • 十一、从头到尾解析Hash算法

    万次阅读 多人点赞 2011-03-17 15:40:00
    十一、从头到尾彻底解析Hash 算法作者:July、wuliming、pkuoliver 出处:http://blog.csdn.net/v_JULY_v。 说明:本文分为三...第三部分为打造一最快的Hash算法。------------------------------------ 第
  • Mysql数据库分区深入详解

    万次阅读 多人点赞 2016-10-21 20:50:46
    0、mysql数据库分区的由来?1)传统不分区数据库痛点...一张主要对应着三文件,一是frm存放结构的,一是myd存放数据的,一是myi存索引的。[root@laoyang test]# ls -al 总用量 1811444 drwx------ 2
  • 表情识别(一)--传统方法概述

    万次阅读 多人点赞 2018-04-25 10:58:38
    一般的表情识别可以用单个感官完成,也可以用多个感官相配合来完成。它是一个整体识别和特征识别共同作用的结果。具体说来,远处辨认人,主要是整体识别,而在近距离面部表情识别中,特征部件识别则更重要。另外,人...
  • oracle 多表联合查询总结归纳

    万次阅读 多人点赞 2014-09-15 20:57:39
    本次预计讲解的知识点 ...在之前所使用的查询操作之中,都是从一张之中查询出所需要的内容,那么如果现在一查询语句需要显示张表的数据,则就必须应用到多表查询的操作,而多表查询的语法如下:
  • (2)基于单设计的多表设计原则(含拆分原则);(均以实际生产开发环境下的环境为基准)文章目录:(1)单设计与优化设计规范化,消除数据冗余(以使用正确字段类型最明显) 前三范式所有字段类型 - 所有...
  • 《流浪地球》上座率在平均值以上,无论从哪个角度看都是一部好电影,无懈可击。 值得欣慰的是,上座率排名靠前的基本都是国产电影,看的出来国外电影尚不能满足大多数人的口味。 5、做点其他分析 电影...
  • Mysql多表查询效率的研究(一)

    万次阅读 2017-08-18 21:44:10
    Mysql多表查询效率的研究(一)本文探究了mysql InnoDB引擎在多表查询的应用场景下,使用子、内连接和左联接运行速度的差别,并且比较了索引使用与否对查询效率的影响。 第一部分简略地概括了索引、子查询、...
  • 蒙特卡洛方法的理解、推导和应用

    万次阅读 多人点赞 2019-06-17 08:27:18
    蒙特卡洛法的简介、基本思想、定积分、理解平均值法、 π 值
  • 上一节对数据库的知识做了一小总结,实际找工作过程中,因为公司或单位侧重点不一样,考察的知识也是不尽相同的,但是作为计算机类的学生,操作系统的知识也是必不可少的,去年参加笔试面试的时候,腾讯微软阿里等...
  • 多表查询 查询每雇员的编号,姓名,职位,工资,部门名称,部门位置。 SELECT e.empno,e.ename,e.job,e.sal,d.dname,d.loc FROM emp e,dept d WHERE e.deptno=d.deptno; 1.全连接 查询每雇员的编号,...
  • 工作目录: 1.BIB文件: <pre name="code" class="javascript">@BOOK{ML12, AUTHOR = {Peter Harrington}, TITLE = {Machine Learning in Action}, PUBLISHER = {Manning Publicat...
  • Oracle管理

    万次阅读 2015-11-21 13:59:19
    Oracle管理 oracle的管理(数据类型,结构创建,修改和删除,数据CRUD操作) 表名和列的命名规则  必须以字母开头  长度不能超过30字符  不能使用oracle的保留字  只能使用如下字符 A-Z,a-z,0-9,...
  • 据说打开这篇文章的人,工作时间成本都降低了60%
  • 笛卡尔集会在下面条件下产生:省略连接条件、连接条件无效、所有中的所有行互相连接。 为了避免笛卡尔集, 可以在 WHERE 加入有效的连接条件。在实际运行环境下,应避免使用全笛卡尔集。 使用CROSS JOIN 子句使...
  • 现在已经到了一重要的分水岭阶段:通用性和兼容性能力成为大数据发展主流,运行的稳定可靠和使用的简捷、易开发、易维护成为产品发展的驱动力,而这正是 Hadoop/Spark 这类积木式模块框架无法满足的。 本 Chat ...
  • 以太坊的工作原理

    万次阅读 2019-05-02 14:39:17
    最近在新闻里出现过很次,包括一些专业杂志的封面,但是如果你们对以太坊到底是什么没有一基本的了解的话,看这些文章就会感觉跟看天书一样。 所以,什么是以太坊?本质上,就是一保存数字交易永久记录的公共...
  • 原文转自:... 问题描述: 近几天发现Oracle10.2.0.4数据库undo tablespace空间使用率很高(最高时达到100%),报警系统频繁报障undo tablespace空间使用率过高。 TABLESPACE_NAME TOTAL USED
  • 超硬核!数据结构学霸笔记,考试面试吹牛就靠它

    万次阅读 多人点赞 2021-03-26 11:11:21
    上次发操作系统笔记,很快浏览上万,这次数据结构比上次硬核的哦,同样的会发超硬核代码,关注吧。
  • 一共81,开源大数据处理工具汇总

    万次阅读 2017-03-14 16:08:26
    查询引擎 一、Phoenix 贡献者::Salesforce 简介:这是一个Java中间层,可以让开发者在Apache HBase上...Phoenix查询引擎会将SQL查询转换为一个或多个HBase scan,并编排执行以生成标准的JDBC结果集。直接使用HB
  • 一般情况下, 在传感器中,实际像素要比有效像素, 如下图所示, 像素区头几行作为不感光区( 实际上,这部分区域也做了RGB 的 color filter),用于自动黑电平校正,其平均值作为校正值, 然后在下面区域的像素都...
  • 堆积是一近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法: 1、大顶堆(大根堆):每节点...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 78,889
精华内容 31,555
关键字:

多个工作表满足条件求平均值