学数据库还不会Select,SQL Select详解,单表查询完全解析?

查询操作是SQL语言中很重要的操作,我们今天就来详细的学习一下。

一、数据查询的语句格式

 SELECT [ALL|DISTINCT] <目标列表达式>[<目标列表达式> ....] --可以选择多个列
FROM <表名或视图名>[<表名或视图名> ....]--可以选择多个表或视图
[ WHERE <条件表达式> ]  --查询什么条件的数据
[ GROUP BY <列名1> [ HAVING <条件表达式> ] ]  --按什么条件分组
[ ORDER BY <列名2> [ ASC|DESC ] ]--按什么条件排序

  • SELECT子句:指定要显示的属性列
  • FROM子句:指定查询对象(基本表或视图)
  • WHERE子句:指定查询条件
  • GROUP BY子句:
    细化聚集函数的作用对象
    • 未对查询结果分组,聚集函数将作用于整个查询结果
    • 对查询结果分组后,聚集函数将分别作用于每个组
    • 作用对象是查询的中间结果表
    • 按指定的一列或多列值分组,值相等的为一组

合计函数 (比如 SUM) 常常需要添加 GROUP BY 语句。

例子:
BILL表

Customer Quantity Date
张三 10 2020-3-19
李四 29 2020-3-19
王五 9 2020-3-19
张三 21 2020-3-19
王五 19 2020-3-20

执行SELECT Customer ,SUM(Quantity) FROM BILL GROUP BY Customer
我们会得到如下表

Customer Quantity
张三 31
李四 29
王五 28

如果我们不加GROUP BY 会得到这样一个表

Customer Quantity
张三 88
李四 88
王五 88
张三 88
王五 88

当然GROUP BY也可以按多个列分组,即两个都想同时才会被分到一个组
还是对BILL表操作 SELECT Customer ,SUM(Quantity) FROM BILL GROUP BY Customer,Date
我们会得到如下表

Customer Quantity
张三 31
李四 29
王五 9
王五 19
  • HAVING短语:
    筛选出只有满足指定条件的组
    例子:
    BILL表

    Customer Quantity Date
    张三 10 2020-3-19
    李四 29 2020-3-19
    王五 9 2020-3-19
    张三 21 2020-3-19
    王五 19 2020-3-20

    我们查询购买总量小于30的Customer

    SELECT  Customer,SUM(Quantity)  From BILL 
    GROUP BY Customer
    HAVING SUM(Quantity)>30
    

    我们会得到如下:

    Customer Quantity
    张三 31
  • ORDER BY子句:对查询结果表按指定列值的升序或降序排序
    还是对BILL表操作

    Customer Quantity Date
    张三 10 2020-3-19
    李四 29 2020-3-19
    王五 9 2020-3-19
    张三 21 2020-3-19
    王五 19 2020-3-20

    我们想按照购买总数量排列查询结果

    SELECT Customer ,SUM(Quantity) FROM BILL 
    GROUP BY Customer
    ORDER BY SUM(Quantity) ASC
    

    我们会得到如下表

    Customer Quantity
    王五 28
    李四 29
    张三 31

ORDER BY子句

  • 可以按一个或多个属性列排序
  • 升序:ASC;降序:DESC;缺省值为升序
  • 当排序列含空值时
  • ASC:排序列为空值的元组最后显示
  • DESC:排序列为空值的元组最先显示

二、单表查询

刚才在介绍那几个保留字的时候,我们简单的举了几个查询的例子,现在我们详细系统的介绍一下,有点重复,但是比较基础,加深印象。

1.选择表中的若干列查询

选择某几列查询:

SELECT <1>,<2>......
FROM <数据表>;

选择全部列查询:
当然我们可以,把所有的列一一列举,我们也可以使用SELECT *

SELECT  *
FROM <数据表>

举例:
还是BILL表

Customer Quantity Date
张三 10 2020-3-19
李四 29 2020-3-19
王五 9 2020-3-19
张三 21 2020-3-19
王五 19 2020-3-20
SELECT Customer From BILL

得到如下表

Customer
张三
李四
王五
张三
王五

执行:

SELECT Customer ,Quantity,Date FROM BILL
--或者
SELECT * FROM BILL

得到如下结果

Customer Quantity Date
张三 10 2020-3-19
李四 29 2020-3-19
王五 9 2020-3-19
张三 21 2020-3-19
王五 19 2020-3-20
2.查询经过计算的值

之前我们给出了SELECT标准格式:

 SELECT [ALL|DISTINCT] <目标列表达式>[<目标列表达式> ....] --可以选择多个列
FROM <表名或视图名>[<表名或视图名> ....]--可以选择多个表或视图
[ WHERE <条件表达式> ]  --查询什么条件的数据
[ GROUP BY <列名1> [ HAVING <条件表达式> ] ]  --按什么条件分组
[ ORDER BY <列名2> [ ASC|DESC ] ]--按什么条件排序

其中目标表达式可以为:

  • 算术表达式
  • 字符串常量
  • 函数
  • 列别名

例子:
Students表

Name Birth
李勇 1999
刘晨 1997
王敏 1996
张立 1998

我们查询每个人的年龄:

SELECT NAME,2020-Birth    
FROM Student;

得道如下的查询结果:

Name 2020-Birth
李勇 21
刘晨 23
王敏 24
张立 22

在查询中添加新的字符串列
例子

Name Birth
李勇 1999
刘晨 1997
王敏 1996
张立 1998
SELECT  Name,'Birth is:',Birth
FROM Students ;

结果:

Name ‘Birth is:’ Birth
李勇 Birth is: 1999
刘晨 Birth is: 1997
王敏 Birth is: 1996
张立 Birth is: 1998

查询中显示列别名
例子
Students表

Name Birth
李勇 1999
刘晨 1997
王敏 1996
张立 1998
SELECT  Name 姓名, Birth 生日
FROM Students ;

结果

姓名 生日
李勇 1999
刘晨 1997
王敏 1996
张立 1998
3.选择表中的若干元组(行)

元组(tuple)是关系数据库中的基本概念,关系是一张表,表中的每行(即数据库中的每条记录)就是一个元组,每列就是一个属性。 在二维表里,元组也称为行。

DISTINCT 语句:
指定DISTINCT关键词,去掉表中重复的行
例子:
BILL表

Customer Quantity Date
张三 10 2020-3-19
李四 29 2020-3-19
王五 9 2020-3-19
张三 21 2020-3-19
王五 19 2020-3-20

我们执行以下语句查看区别:

SELECT DISTINCT Customer FROM BILL 
Customer
张三
李四
王五

如果不加DISTINCT,结果如下:

Customer
张三
李四
王五
张三
王五

作用显而易见

查询满足条件的元组:

常用的查询条件 谓词
比 较 =,>,<,>=,<=,!=,<>,!>,!<;NOT+上述比较运算符
确定范围 BETWEEN AND,NOT BETWEEN AND
确定集合 IN,NOT IN
字符匹配 LIKE,NOT LIKE
空 值 IS NULL,IS NOT NULL
多重条件(逻辑运算) AND,OR,NOT

这次我们多举几个例子:
Student表

Sname Sage Sdept Sgrade Ssex
张三 18 C.S 80 1
李四 18 C.S 72 0
王五 17 I.C.S 63 0
韩六 18 C.S 98 1
周七 19 I.C.S 34 0
赵八 20 C.S 60 1

以下所有查询的基本表都默认为Student表

例一: 查询计算机科学系全体学生的名单

SELECT Sname
    FROM Student
    WHERE Sdept='C.S.'

结果:

Sname
张三
李四
韩六
赵八

例二: 查询所有年龄在18岁以上的学生姓名及其年龄。

SELECT Sname,Sage 
FROM    Student    
WHERE Sage>18

结果

Sname Sage
周七 19
赵八 20

BETWEEN…AND…语句
例三: 查询年龄在18~20岁(包括18岁和20岁)之间的学生的姓名、系别和年龄

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

结果

Sname Sage Sdept
张三 18 C.S
李四 18 C.S
韩六 18 C.S
周七 19 I.C.S
赵八 20 C.S

例四: 查询年龄在18~20岁(包括18岁和20岁)之间的学生的姓名、系别和年龄

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

结果

Sname Sage Sdept
王五 17 I.C.S

IN/NOT IN语句
例四: 查询年龄为17 和 20岁的学生姓名,年龄及专业

SELECT Sname,Sage,Sdept
FROM     Student
WHERE   Sage IN (1720);

结果

Sname Sage Sdept
王五 17 I.C.S
赵八 20 C.S

例五: 查询年龄不为17 和 20岁的学生姓名,年龄及专业

SELECT Sname,Sage,Sdept
FROM     Student
WHERE   Sage NOT IN (1720);
Sname Sage Sdept
张三 18 C.S
李四 18 C.S
韩六 18 C.S
周七 19 I.C.S

字符串匹配:
语法格式:
谓词:
[NOT] LIKE ‘<匹配串>’ [ESCAPE ‘ <换码字符>’]
<匹配串>:指定匹配模板
匹配模板:固定字符串或含通配符的字符串
当匹配模板为固定字符串时,
可以用 = 运算符取代 LIKE 谓词
用 != 或 < >运算符取代 NOT LIKE 谓词

通配符:

通配符 描述
% 代表任意长度(长度可以为0)的字符串
_ 仅替代一个字符
[charlist] 字符列中的任何单一字符
[^charlist]或者[!charlist] 不在字符列中的任何单一字符

例:
a%b表示以a开头,以b结尾的任意长度的字符串。如acb,addgb,ab 等都满足该匹配串
a_b表示以a开头,以b结尾的长度为3的任意字符串。如acb,afb等都满足该匹配串
ESCAPE 短语:
当用户要查询的字符串本身就含有 % 或 _ 时,要使用ESCAPE ‘<换码字符>’ 短语对通配符进行转义。

类型1: 匹配串为固定字符串
查询学号为200215121的学生的详细情况。

  SELECT *    
     FROM  Student  
     WHERE  Sno LIKE200215121';

等价于:

  SELECT  * 
  FROM  Student 
  WHERE Sno = ' 200215121 '

类型2: 匹配串为含通配符的字符串

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

  SELECT Sname,Sno,Ssex
  FROM Student
  WHERE  Sname LIKE ‘刘%’;

查询姓"欧阳"且全名为三个汉字的学生的姓名。

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

查询名字中第2个字为"阳"字的学生的姓名和学号。

  SELECT Sname,Sno
  FROM Student
  WHERE Sname LIKE ‘__阳%’;

查询所有不姓刘的学生姓名。

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

类型3: 使用换码字符将通配符转义为普通字符

查询DB_Design课程的课程号和学分。

  SELECT Cno,Ccredit
  FROM Course
  WHERE Cname LIKE 'DB\_Design' ESCAPE '‘;

查询以"DB_"开头,且倒数第3个字符为 i的课程的详细情况。

  SELECT  *
  FROM   Course
  WHERE  Cname LIKE  'DB\_%i_ _' ESCAPE '  ‘;

ESCAPE ‘\’ 表示“ \” 为换码字符
学过C++的大家都知道 代表换行,为转义字符。这里是说,我们通过ESCAPE语句将定义为换码字符(可以理解为转义字符)

类型4: 涉及空值的查询

谓词:IS NULL 或 IS NOT NULL 而且 “IS” 不能用 “=” 代替。
如果某些同学的信息不完整,比如在某个表中手机号未填写,那这位同学的元组中的手机号这一属性为NULL;
要想查出这类同学的姓名我们可以执行以下操作

Student表

Sname Sage Sdept Sgrade Ssex Spho
张三 18 C.S 80 1 12345678
李四 18 C.S 72 0 12345679
王五 17 I.C.S 63 0 12345680
韩六 18 C.S 98 1 NULL
周七 19 I.C.S 34 0 234234234
赵八 20 C.S 60 1 NULL
SELECT Sname,Spho From Student
WHERE Spho IS NULL;
Sname Spho
韩六 NULL
赵八 NULL

类型5: 多重条件查询
逻辑运算符:
AND:且 连接前后两个条件都成立时表达式为真
OR:或 连接前后表达式有一个为真时表达式为真
AND优先级大于OR,可以加括号进行复合运算,进而改变优先级。

常用的查询条件 谓词
比 较 =,>,<,>=,<=,!=,<>,!>,!<;NOT+上述比较运算符
确定范围 BETWEEN AND,NOT BETWEEN AND
确定集合 IN,NOT IN
字符匹配 LIKE,NOT LIKE
空 值 IS NULL,IS NOT NULL
多重条件(逻辑运算) AND,OR,NOT

可以连接上面表中的所有运算符,只要保证最后得到表达可以分辨真假有意义即可。

这个比较简单我们举一个例子:
查询18岁的学生且属于计算机科学专业的姓名,年龄,专业

Sname Sage Sdept Sgrade Ssex Spho
张三 18 C.S 80 1 12345678
李四 18 C.S 72 0 12345679
王五 17 I.C.S 63 0 12345680
韩六 18 C.S 98 1 NULL
周七 19 I.C.S 34 0 234234234
赵八 20 C.S 60 1 NULL
SELECT Sname,Sage,Sdept FROM Students
WHERE Sage=18 AND Sdept='C.S.';
Sname Sage Sdept
张三 18 C.S
李四 18 C.S
韩六 18 C.S
4.聚集函数

计数
SQL COUNT(column_name) 语法
COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入):

SELECT COUNT(column_name) FROM table_name

SQL COUNT(*) 语法
COUNT(*) 函数返回表中的记录数:

SELECT COUNT(*) FROM table_name

SQL COUNT(DISTINCT column_name) 语法
COUNT(DISTINCT column_name) 函数返回指定列的不同值的数目:

SELECT COUNT(DISTINCT column_name) FROM table_name

例:
查询学生总人数。

SELECT COUNT(*)
FROM  Student;

查询选修了课程的学生人数。

 SELECT COUNT(DISTINCT Sno)
 FROM SC

计算总和

SQL SUM() 语法

SELECT SUM(column_name) FROM table_name

开头举过例子,这里就不再重复赘述。

计算平均值

AVG 函数返回数值列的平均值。NULL 值不包括在计算中。

SQL AVG() 语法

SELECT AVG(column_name) FROM table_name


计算1号课程的学生平均成绩。

  SELECT AVG(Grade)
  FROM SC
  WHERE Cno=1 ’;

最大最小值

MAX() 函数和MIN()函数
MAX 函数返回一列中的最大值,MIN 函数返回一列中的最小值。NULL 值不包括在计算中。

SQL中的语法

SELECT MAX(column_name) FROM table_name
SELECT MIN(column_name) FROM table_name

MIN 和 MAX 也可用于文本列,以获得按字母顺序排列的最高或最低值。
例:
查询选修1号课程的学生最高分数。

   SELECT MAX(Grade)
   FROM SC
   WHERE Cno=1 ’;