• 数据库——SQL数据单表查询


     数据查询

    语句格式

    SELECT [ALL|DISTINCT] <目标列表达式>     [,<目标列表达式>] …
    FROM <表或视图名>[,<表或视图名> ] …
    [ WHERE <条件表达式> ]
    [ GROUP BY <列名1> 
          [ HAVING <条件表达式> ] ]
    [ ORDER BY <列名2> [ ASC|DESC ] ];
     

    SELECT子句:指定要显示的属性列
    FROM子句:指定查询对象(基本表或视图)
    WHERE子句:指定查询条件
    GROUP BY子句:对查询结果按指定列的值分组,该属性列值相等的元组为一个组。通常会在每组中作用集函数。
    HAVING短语:筛选出只有满足指定条件的组
    ORDER BY子句:对查询结果表按指定列值的升序或降序排序

     示例数据库

    学生表:
          Student(Sno,Sname,Ssex,Sage,Sdept)
    课程表:
          Course(Cno,Cname,Cpno,Ccredit)
    选课表:
          SC(Sno,Cno,Grade)

    1.单表查询

    查询仅涉及一个表,是一种最简单的查询操作
    一、选择表中的若干列
    二、选择表中的若干元组
    三、对查询结果排序
    四、使用集函数
    五、对查询结果分组

    一、选择表中的若干列

    1查询指定列

    [例1]  查询全体学生的学号与姓名。

    SELECT Sno,Sname
    FROM Student; 


    [例2]  查询全体学生的姓名、学号、所在系。

    SELECT Sname,Sno,Sdept
    FROM Student;

    语句不分大小写,一般分行写,分号可不写

    2查询全部列

    [例3]  查询全体学生的详细记录。

    SELECT  Sno,Sname,Ssex,Sage,Sdept 
    FROM Student; 
       或
    SELECT  *
    FROM Student;

    3. 查询经过计算的值

    [例4]  查全体学生的姓名及其出生年份。

    SELECT Sname,2015-Sage
    FROM Student; 

    输出结果:
                  Sname   2015-Sage
                 ---------    -------------
                   李勇       1986
                   刘晨       1987
                   王名       1988
                   张立       1988

    [例5]  查询全体学生的姓名、出生年份和所有系,要求用小写字母表示所有系名。

    SELECT Sname,'Year of Birth: '2015- Sage, ISLOWER(Sdept)
    FROM Student; 

    字符串常量用单引号

    输出结果:
        Sname     'Year of Birth:'      2015-Sage   ISLOWER(Sdept)
       -------  ------------  -------  -----------
          李勇    Year of Birth:    1986       cs
           刘晨    Year of Birth:    1987       is
           王名    Year of Birth:    1988       ma
           张立    Year of Birth:    1987       is

    ISLOWER是ORACLE的函数名
    SQL-SERVER的函数名是LOWER

    SELECT Sname,'Year of Birth: '2015 -Sage, LOWER(Sdept)
    FROM Student; 

    [例5.1] 使用列别名(可选)改变查询结果的列标题

    SELECT Sname  NAME,'Year of Birth: '  BIRTH,
      2015-Sage  BIRTHDAY,LOWER(Sdept)  DEPARTMENT
    FROM Student;

    输出结果:
         NAME    BIRTH                  BIRTHDAY   DEPARTMENT
       -------  ----------------    ----------  -------------
         李勇    Year of Birth:    1986           cs
         刘晨    Year of Birth:    1987           is
         王名    Year of Birth:    1988           ma
         张立    Year of Birth:    1987           is

    二、选择表中的若干元组

    1. 消除取值重复的行

    在SELECT子句中使用DISTINCT短语
    假设SC表中有下列数据   
        Sno       Cno       Grade
                  -------    -------     -------
                  95001       1         92
                  95001       2         85
                  95001       3         88
                  95002       2         90
                  95002       3         80


    [例6]  查询选修了课程的学生学号。
    (1)

     SELECT Sno
          FROM SC;

    结果:   Sno   
                  -------
                  95001  
                  95001  
                  95001  
                  95002  
                  95002
    (2) 

    SELECT DISTINCT Sno
             FROM SC;

    结果:
                  Sno   
                  -------
                  95001  
                  95002

    2.查询满足条件的元组

    (1) 比较大小
    在WHERE子句的<比较条件>中使用比较运算符
    =,>,<,>=,<=,!= 或 <>,!>,!<,
    逻辑运算符NOT

    [例8]  查询所有年龄在20岁以下的学生姓名及其年龄。
     

    SELECT Sname,Sage
    FROM    Student    
    WHERE Sage < 20

    [例]  查询计算机系的学生姓名及其年龄。

    SELECT Sname,Sage
    FROM    Student    
    WHERE Sdept='CS'

    (2) 确定范围

    使用谓词   BETWEEN …  AND  …
                            NOT BETWEEN  …  AND  …

    [例10]  查询年龄在20~23岁(包括20岁和23岁)之间的学生的姓名、系别和年龄。

    SELECT Sname,Sdept,Sage
    FROM   Student
    WHERE Sage BETWEEN 20 AND 23

    [例11]  查询年龄不在20~23岁之间的学生姓名、系别和年龄。

    SELECT Sname,Sdept,Sage
    FROM    Student
    WHERE Sage NOT BETWEEN 20 AND 23

    (3) 确定集合


    使用谓词     IN (值表),  NOT IN (值表)
              值表:用逗号分隔的一组取值

    [例12]查询信息系(IS)、数学系(MA)和计算机科学系(CS)学生的姓名和性别。

    SELECT Sname,Ssex
    FROM  Student
    WHERE Sdept IN ( 'IS''MA''CS' );

    [例13]查询既不是信息系、数学系,也不是计算机科学系的学生的姓名和性别。

    SELECT Sname,Ssex
    FROM Student
         WHERE Sdept NOT IN ( 'IS''MA''CS' );

    (4) 字符串匹配

    [NOT] LIKE  ‘<匹配串>’
    <匹配串>:含精确匹配字符和通配符
          
    模糊匹配---通配符

    % (百分号)  代表任意长度(长度可以为0)的字符串
    例:a%b表示以a开头,以b结尾的任意长度的字符串。如acb,addgb,ab 等都满足该匹配串
    _ (下横线)  代表任意单个字符
    例:a_b表示以a开头,以b结尾的长度为3的任意字符串。如acb,afb等都满足该匹配串

    1) 匹配串为固定字符串


    [例14]  查询姓名为'刘晨'学生的详细情况。
       

         SELECT *    
         FROM  Student  
         WHERE  Sname LIKE '刘晨';
    等价于:
          SELECT  *
          FROM  Student
          WHERE  Sname = '刘晨'

    2) 匹配串为含通配符的字符串

    [例15]  查询所有姓刘学生的姓名、学号和性别。
      

       SELECT Sname,Sno,Ssex
          FROM Student
          WHERE  Sname LIKE '刘%'

    [例16]  查询姓"欧阳"且全名为三个字的学生的姓名。
        

     SELECT Sname
          FROM   Student
          WHERE  Sname LIKE '欧阳_'

    [例17]  查询名字中第2个字为‘阳’字的学生的姓名和学号。
         

         SELECT Sname,Sno
          FROM Student
          WHERE Sname LIKE   '_阳%'

    [例18]  查询所有不姓刘的学生姓名。
     

      SELECT Sname,Sno,Ssex
          FROM Student
          WHERE Sname NOT LIKE '刘%'

    (5) 涉及空值的查询


     使用谓词 IS NULL 或 IS NOT NULL
     “IS NULL” 不能用 “= NULL” 代替


    [例21]  某些学生选修课程后没有参加考试,所以有选课记录,但没有考试成绩。查询缺少成绩的学生的学号和相应的课程号。
     

       SELECT Sno,Cno
          FROM SC
          WHERE Grade IS NULL;

    [例22]  查所有有成绩的学生学号和课程号。
      

       SELECT Sno,Cno
          FROM  SC
          WHERE  Grade IS NOT NULL;

    (6) 多重条件查询

    用逻辑运算符AND和 OR来联结多个查询条件
     AND的优先级高于OR
     
    [例23]  查询计算机系年龄在20岁以下的学生姓名。
        

    SELECT Sname
           FROM  Student
           WHERE Sdept= 'CS' AND Sage<20

    改写[例12]
    例12]  查询信息系(IS)、数学系(MA)和计算机科学系(CS)学生的姓名和性别。

    SELECT Sname,Ssex
    FROM Student
    WHERE Sdept IN ( 'IS''MA''CS' )

    可改写为:

    SELECT Sname,Ssex
    FROM   Student
    WHERE  Sdept= ' IS ' OR Sdept= ' MA' OR Sdept= ' CS '

    改写[例10]
    [例10]  查询年龄在20~23岁(包括20岁和23岁)之间的学生的姓名、系别和年龄。     

    SELECT Sname,Sdept,Sage
    FROM Student
    WHERE Sage BETWEEN 20 AND 23

        可改写为:

    SELECT Sname,Sdept,Sage
    FROM Student
    WHERE  Sage>=20 AND Sage<=23


    三、对查询结果排序

    使用ORDER BY子句
     可以按一个或多个属性列排序
     升序:ASC;(缺省)
     降序:DESC;
     

    [例24]  查询选修了3号课程的学生的学号及其成绩,查询结果按分数降序排列。

      SELECT Sno,Grade
        FROM  SC
        WHERE  Cno= ' 3 '
        ORDER BY Grade DESC; 

    [例25]  查询全体学生情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列。

        SELECT  *
        FROM  Student
        ORDER BY Sdept,Sage DESC;

    四、使用集函数

    5类主要集函数
    1. 行计数COUNT
    2. 计算总和SUM    
    3. 计算平均值AVG
    4. 求最大值 MAX     
    5. 求最小值MIN

    行计数的两种形式
    (1) COUNT(*)
          对每行计数
     

    [例26]  查询学生总人数。

      SELECT COUNT(*)
        FROM  Student;
     

    查询计算机系的学生人数

        SELECT COUNT(*)
        FROM  Student
        WHERE SDEPT=‘CS’

    查询1号课不及格人数

        SELECT COUNT(*)
        FROM  SC
        WHERE CNO=1 AND GRADE<60

    (2)COUNT( <列名> )
    对<列名>非空的行计数
    COUNT( [DISTINCT|ALL] <列名> )
           DISTINCT:计数时要先取消指定列中的重复值
           ALL:不取消重复值,ALL为缺省值

    [例27]  查询选修了课程的学生人数。

    SELECT COUNT(DISTINCT Sno)
      FROM SC;

    注:对Sno非空的行,排除重复Sno计数。
           以避免重复计算学生人数
     

    有什么区别?

    (1)    
    SELECT COUNT(*) FROM SC; 对SC每行计数

    (
    2)
    SELECT COUNT(Sno) FROM SC; Sno非空行计数,因Sno为主属性,所以与(1)相同

    (
    3)
    SELECT COUNT(DISTINCT Sno) FROM SC;
    SNO去重复行计数
    (
    4)
    SELECT COUNT(Grade) FROM SC;
    GRADE非空行计数

    [例28]  计算1号课程的学生平均成绩。

    SELECT AVG(Grade)
       FROM SC
       WHERE Cno= ' 1 '

    (成绩为null的行不参与计算)


    [例29]  查询选修1号课程的学生最高分数。

    SELECT MAX(Grade)
         FROM SC
         WHER Cno= ' 1 '

    [例]  计算1号课程的平均成绩,最高分,最低分,选课人数

     SELECT AVG(Grade), MAX(Grade),MIN(Grade), COUNT(*)
       FROM SC
       WHERE Cno= ' 1 '

    五、对查询结果分组

    使用GROUP BY子句分组     
    细化集函数的作用对象
     未对查询结果分组,集函数将作用于整个查询结果
     对查询结果分组后,集函数将分别作用于每个组

    分组后的聚集函数将作用于每一个组,即每一个组都有一个函数值

    同时这个分组是先进行的排序,这也是为什么分组后的结果是按照顺序排列的。

    使用GROUP BY子句分组

    [例30]  求各个课程号及相应的选课人数,平均成绩。 

    SELECT Cno,COUNT(*),AVG(Grade)
         FROM    SC
         GROUP BY Cno;
     

    结果
                 Cno        COUNT(*)    AVG(Grade)
                 1             22                    75
                 2             34                    80
                 3             44                    78

    易犯错误:

    SELECT Sno, Cno, COUNT(*),AVG(Grade)--在统计查询中,这里只允许有分组属性和集函数
       FROM    SC
       GROUP BY Cno;

    [例30]  求各个课程号及相应的选课人数,平均成绩。

    SELECT Cno,COUNT(*) ,AVG(Grade)
         FROM    SC
         GROUP BY Cno; 

    对具有可分组的列分组,输出这个列和统计信息

    用多个列分组

    [例31]  查询每个系男女生人数。

    SELECT Sdept, Ssex, COUNT(*)
         FROM    Student
         GROUP BY Sdept, Ssex;

    如果分组后还要求按一定的条件对这些组进行筛选,最终只输出满足指定条件的组,则使用HAVING短语筛选最终输出结果

    [例32]  查询选修了3门以上课程的学生学号。
      

     SELECT Sno
         FROM  SC
         GROUP BY Sno
         HAVING  COUNT(*) >=3

    [例33]  查询有3门以上课程是90分以上的学生的学号及(90分以上的)课程数

     SELECT  Sno,  COUNT(*)
     FROM   SC
     WHERE Grade>=90
     GROUP BY Sno
     HAVING COUNT(*)>=3;     

    WHERE子句与HAVING短句的区别在于作用对象不同。

    WHERE子句作用于基本表或视图,从中选择满足条件的元组(表中的一行)

    HAVING短句作用于组,从中选择满足条件的组。

  • 相关阅读:
    九.Protobuf3特殊类型
    八.Protobuf3更新消息类型(添加新的字段)
    七.Protobuf3 嵌套类型
    六.Protobuf3引入其他.proto文件
    五.Protobuf3 枚举
    四.Protobuf3 缺省值
    VC 在调用main函数之前的操作
    Windows下的代码注入
    C 堆内存管理
    VC++ 崩溃处理以及打印调用堆栈
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/10627795.html
Copyright © 2020-2023  润新知