数据库查询

一、数据查询语句的基本格式

二、单表查询

查询表中的若干列

查询指定列

查询经过计算的值

选择表中的若干元组

去重

条件查询

order by 子句

聚集函数

group by 子句

三、连接查询

等值与非等值连接查询

外连接

多表连接

四、嵌套查询

带有in谓词的子查询

带有比较运算符的子查询

带有any(some)或all谓词的子查询

带有exists谓词的子查询

五、集合查询

六、基于派生表的查询

一、数据查询语句的基本格式

    select 要查的内容

    from 查找的对象

    where 查找的条件

    group by 按什么分组

    having 使用到函数的条件

    order by 按照什么条件排序

二、单表查询

查询表中的若干列

查询指定列

    select 列名1,列名2[,列名3,...]

    from 表名;

        如果要查询表中的所有列并且不用列的显示顺序,那么可以用符号“*”来代替所有列名,如果想要改变显示顺序,那么就要将所有的表名按照你想要的顺序写出来。

        如果想要显示自己指定的列名可以在要查询的列名的后面加一个空格,然后输入自己想要的列名即可。

查询经过计算的值

        如果想要查询出经过一定的处理的列值,那么只需要将列名换成表达式即可,表达式可以是算术表达式、函数和字符串常量等

例:查询全体学生的姓名、出生年份和所在院系,要求给出生年份起别名:birthday,用小写字母表示系名

    select Sname,2022-Sage birthday,lower(Sdept)

    from Student;

选择表中的若干元组

去重

        有时候我们查到的结果可能是重复的,如果我们想要消除这些行可以使用distinct来消除它们。

例:查询选修了课程的学生学号,并去除重复的行。

    select distinct Sno

    from Sc;

条件查询

        条件查询可以通过where子句实现,下面是where子句的常用查询条件。

查询条件 谓词

比较 =,>,<,>=,<=,!=,<>,!>,!<;NOT+上述比较运算符

确定范围 between and,not between and

确定集合 in,not in

字符匹配 like,not like

空值 is null,is not null

多重条件(逻辑运算) and,or,not

(1)比较大小

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

    select Sname

    from Student

    where Sdept = 'CS';

(2)确定范围

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

    select Sname,Sdept,Sage

    from Student

    where Sage between 20 and 23;

(3)确定集合

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

    select Sname,Ssex

    from Student

    where Sdept in ('CS','MA','IS');

(4)字符匹配

        在字符匹配中,%代表任意长度(可以为0)的字符串,下划线代表任意单个字符。如果要查询的字符串中含有%或者下划线则可以用 escape 定义换码字符。当匹配串中不含通配符时,可以用等于运算符代替like谓词,用不等于运算符代替not like谓词。

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

    select *

    from Course

    where Cname like 'DB\_%i__' escape '\';

(5)涉及空值的查询

        空值查询中的is和is not不能用等于或者不等于代替,等于或不等于的前提是有值,空值没有值。

例:查询所有有成绩的学生学号和课程号。

    select Sno,Cno

    from Sc

    where Grade is not null

(6)多重条件查询

        逻辑运算符and和or可以用来连接多个查询条件。and的优先级高于or,但用户也可以用括号改变优先级。

例:查询计算机科学系年龄在20岁以下的学生姓名。

    select Sname

    from Student

    where Sdept = 'CS' and Sage > 20;

order by 子句

        order by子句用来给查询结果排序,ASC为升序排列,DESC为降序排列,默认值为升序。空值的显示次序有具体系统实现来决定。

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

    select *

    from Student

    order by Sdept ASC,Sage DESC

聚集函数

        为了进一步方便用户,增强检索功能,下面是常用的一些聚合函数。

函数名 作用

count(*) 统计元组个数

count([distinct|all] <列名>) 统计一列中值的个数

sum([distinct|all] <列名>) 计算一列值的总和,列值必须是数值型

avg([distinct|all] <列名>) 计算一列值的平均值,列值必须是数值型

max([distinct|all] <列名>) 求一列值中的最大值

min([distinct|all] <列名>) 求一列值中的最小值

注:1.distinct代表计算时去除重复值,all代表计算时不去除重复值,默认为all。

        2.当聚集函数遇到空值时,除count(*)外,都跳过空值而只处理非空值。

        3.聚集函数只能用于select子句和group by中的having子句。

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

    select count(distinct Sno)

    from Sc;

group by 子句

        group by子句将查询结果按某一列或多列的值分组,值相等的为一组。如果未对查询结果分组,聚集函数将作用于整个查询结果,分组后聚集函数将作用于每一组,即每一组都有一个函数值。

例:查询选修了三门以上课程的学生学号。

    select Sno

    from Sc

    group by Sno

    having count(*) > 3;

三、连接查询

        通常情况下,只查询一个表并不能满足我们的需求,这时就引入了连接查询。如果一个查询同时涉及两个以上的表,则称之为连接查询。

等值与非等值连接查询

        连接查询的where子句中用来连接两个表的条件称为连接条件或连接谓词,其一般格式为

    [<表名1>.]<列名1><比较运算符>[<表名2>.]<列名2>

    [<表名1>.]<列名1> between [<表名2>.]<列名2> and [<表名2>.]<列名3>

        当比较运算符为“=”时,称为等值连接,其余则为非等值连接。连接条件中的列名称为连接字段,各连接字段的名称不必相同,但必须是可比的。在等值连接中,去掉目标列中的重复列称为自然连接

例:查询选修2号课程且成绩在90分以上的所有学生的学号和姓名。

    select Student.Sno,Sname

    from Student,Sc

    where Student.Sno = Sc.Sno and Sc.Cno = '2' and Sc.Grade > 90;

    自身连接

        一个表自己与自己连接叫做自身连接。

例:查询每一门课的间接先修课(即先修课的先修课)。

    select first.Cno,second.Cpno

    from Course first,Course second

    where first.Cpno = second.Cno;

外连接

        普通连接操作只输出满足连接条件的元组,外连接操作以指定表为主体,将主体表中不满足连接条件的元组一并输出。外连接分为左外连接和右外连接,如果列出左表中的所有元组,则称为左外连接;列出右表的所有元组,则成为右外连接。

例:查询每个学生及其选修课程的情况,未选课的学生的选课情况以空值输出。

    select Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade

    from Student left outer join Sc on (Student.Sno = Sc.Sno);

    或

    select Student.*,Sc.*

    from Student left outer join Sc using(Sno);

多表连接

        两个表以上的连接称为多表连接

例:查询每个学生的学号、姓名、选修的课程名及成绩。

    select Student.Sno,Sname,Cname,Grade

    from Student,Sc,Course

    where Student.Sno = Sc.Sno and Sc.Cno = Course.Cno;

四、嵌套查询

        在SQL语言中,一个select-from-where语句称为一个查询块。将一个查询块嵌套在另外一个查询块中的where子句或having短语的条件中的查询称为嵌套查询。被嵌套的查询块称为内层查询或子查询,另一个则为外层查询或父查询。需要注意的是,group by子句只能对最终的查询结果进行排序,也就是只能用在最外层的查询中,不能用在任何子查询中。

        如果子查询的条件不依赖于父查询,则称为不相关子查询。如果子查询的条件依赖于父查询,则称为相关子查询。

带有in谓词的子查询

例:查询选修了课程名为“信息系统”的学生的学号和姓名。

    select Sno,Sname

    from Student

    where Sno in

        (select Sno

        from Sc

        where Cno in

            (select Cno

            from Course

            where Cname = '信息系统'

            )

        );

带有比较运算符的子查询

        父查询与子查询之间用比较运算符进行连接,这时内层查询返回的是单个值。

例:找出每个学生超过他自己选修课程平均成绩的课程号。

    select Sno,Cno

    from Sc x

    where Grade >= (

        select avg(Grade)

        from Sc y

        where x.Sno = y.Sno);

带有any(some)或all谓词的子查询

        子查询返回多个值时要用any或all谓词修饰符,并且必须同时使用比较运算符。谓词any的意思是结果中的某个值,all的意思是结果中的所有值。

例:查询非计算机科学系中比计算机科学系所有学生年龄都小的学生姓名及年龄。

    select Sname,Sage

    from Student

    where Sage < all

        (select Sage

        from Student

        where Sdept = 'CS')

    and Sdept <> 'CS';

带有exists谓词的子查询

        此类子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”。由exists引出的子查询,其目标表达式通常用*,因为带exists的子查询只返回真值或假值,给出列名无实际意义。

例:查询选修了全部课程的学生姓名。

    select Sname

    from Student

    where not exists

        (

        select *

        from Course

        where not exists

            (

            select *

            from Sc

            where Sno = Student.Sno and Cno = Course.Cno

            )

        );

五、集合查询

        查询的结果是一个个元组的集合,所以多个查询结果之间可以进行集合操作。集合操作主要包括交(intersect)、并(union)和差(except)。需要注意的是,参加集合操作的各查询结果的列数和对应项的数据类型必须相同。

例:查询计算机科学系的学生及年龄不大于19岁的学生。

    select *

    from Student

    where Sdept = 'CS'

    union

    select *

    from Student

    where Sage <= 19;

注意:并操作会自动去除相同的元组,如果不想去除重复的元组可以用union all操作符。

六、基于派生表的查询

        除去返回逻辑真假值的情况,子查询返回的结果可以认为是一个表,那么子查询的结果就可以作为一个临时派生表出现在from子句中,成为主查询的查询对象。

例:找出每个学生超过他自己选修课程平均成绩的课程号。

    select Sno,Cno

    from Sc,(select Sno,Avg(Grade) from Sc group by Sno)

        as Avg_sc(avg_sno,avg_grade)    -- 给派生表指定表名和属性列名

    where Sc.Sno = Avg_sc.avg_sno and Sc.Grade >= Avg_sc.avg_grade;

注意:1.如果子查询中没有聚集函数,那么可以不给派生表指定属性列名。

          2.通过from子句生成派生表时,as关键字可以省略,但必须为派生关系起一个别名。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容