Python 高级 15(1) 数据表

2.5 数据表查询操作

学习目标

能够熟练对数据表进行各种查询操作

--------------------------------------------------------------------------------

2.5.1 数据查询操作介绍

在数据库操作中,使用频率最多的是查询操作。

查询数据时,根据不同的需求,条件对数据库中的数据进行查询 ,并返回结果。

2.5.2 准备工作,导入数据库

在查询之前,首先要有数据表和相应的数据。

在 辅助资料中 有 school.sql 文件,通过导入该文件来快速准备数据。

  导入之前需要先创建一个数据库

  使用新创建的数据库

  使用 source 文件地址 导入数据

      注意,导入数据库时的文件地址尽量使用绝对路径,或者把文件放在家目录下

2.5.3 单表查询数据

查询数据库使用 select 命令。 这个命令相对比较复杂。可变化样式较多,这里分功能依次讲解。

1.数据表单表查询数据总结:

select 字段名[,(字段名…)] from 表名;

  <1>查询数据表中所有数据

      语法:select * from 表名

      select * from t_student;

  <2>查询指定字段的显示

      语法:select 字段1,字段2,... from 表名

      select c_id,c_name,c_address from t_student;

  <3>as 别名

      在查询时,默认结果显示的字段和表中字段名相同,可以通过别名来修改显示的样

      给字段起别名

          ■  语法:select 字段1 as 别名,字段2 别名,... from 表名

          ■ select c_id as 学号 ,c_name as 姓名 ,c_address 地址 from t_student;

      给数据表起别名

          ■ 语法:select 字段1,字段2 别名,... from 表名 as 别名

      注意:

          ■ 在给字段或表起别名时,可以使用 as ,也可以直接在字段后跟别名,省略 as 。

          ■ 如果起了别名,原名将不起作用!后面的语句中只能使用别名

  <4>消除重复数据distinct

      在查询数据时,查询结果可能会有很多重复的数据,如果不想重复,可以使用 distinct 来实现去重。

      语法:select distinct 字段名 from 表名

      语法:select distinct 字段名1 字段名2 from 表名

      select distinct c_address from t_student;

      注意:

          ■ 可以指定多个字段名

          ■ distinct 在去重时,会比较所有的指定字段,只有完全相同时才认为是重复的。

  <5>带条件查询where

      where 子句 查询数据时,需要根据不同的需求设置条件。 通过 where 子句来设置查询条件

      语法:select 字段名…  form  表名 where  条件;

      select * from t_student where c_gender='男';

      注意:

          ■ where 条件可以使用运算符操作。

  1>比较运算符

      等于: =

      大于: >

      大于等于: >=

      小于: <

      小于等于: <=

      不等于: != 或 <>

          ■ select * from t_student where c_age < 20;

      注意sql中只有一个等号,没有==这种形式

  2>逻辑运算符

      and

      or

      not

          ■ select * from t_student where c_age < 20 and c_gender = '女';

  <6>模糊查询like

      like(这是一个操作符)

      % 表示任意多个任意字符

      _ 表示一个任意字符

          ■ select * from t_student where c_name like '孙';

          ■ select * from t_student where c_name like '孙%';

          ■ select * from t_student where c_name like '孙_';

  <7>范围查询,非连续范围in,连续范围between ... and ...

      in 表示在一个非连续的范围内 , 可以使用 or 实现

          ■ select * from t_students where id in(1,3,8);

      between ... and ... 表示在一个连续的范围内,可以使用 and 实现 ```

          ■ select * from t_students where c_id between 2 and 5;

          ■ 相当于select * from t_students where c_id >=2 and c_id <= 5;

  <8>空判断is null、is not null

      在数据库中,允许在数据添加是没有数据,使用空值来表示。 空值不等于0,也不等于'',需要使用特殊的判断方式

      判断空值

          ■ 语法:is null

              select * from t_student where c_age is null;

      判断非空值

          ■ 语法:is not null

              select * from t_student where c_age is not null;

  <9>查询结果排序order by

      排序order by(子句)是一个在查询数据时非常重要的操作。比如买东西时,想按一定的条件进行有序显示。就需要使用排序

      排序使用 order by 子段名 asc(默认) 升序 / desc 降序

      语法:select * from 表名 order by 列1 asc/desc [,列2 asc/desc,...]

      单字段排序

  select * from t_student order by c_age;

  select * from t_student order by c_age asc;

  默认使用就是升序排序,可以不指定 asc ,效果相同。

      多字段排序

          ■ 可以对多个字段进行排序,只需将字段的排序方式依次写在 order by 后面即可,字段间使用逗号分隔

          ■ select * from t_student order by c_age desc,c_id asc;

  <10>分页查询limit

      查询数据库时,由于数据较多,在显示过程中不可能将数据全部显示。 可以使用分页查询,只显示指定的一部分数据

      语法:select 字段名 from 表名 limit start=0(开始索引默认为0),count(记录条数)

          ■ 从start开始,获取count条数据,start默认值为0

          ■ 需要获取数据的前n条的时候可以直接写 limit n

          ■ select * from t_student limit 3;

          ■ select * from t_student limit 2,3;

          ■ 注意:查询第 N 页 M 条数据,可以通过公式算出:(N - 1) * M

  <11>聚合函数

      在 MySQL 中提供了一些定义好的函数,利用这些函数提供对数据的统计功能,聚合函数一般配合分组功能一起使用。

      1>sum 求和函数 对指定的字段求和

          ■ select sum(c_age) from t_student;

      2>avg 求平均值函数 对指定字段求平均值

          ■ select avg(c_age) from t_student;

      3>max 求最大值函数

          ■ select max(c_age) from t_student where c_gender = '男';

      4>min 求最小值函数

          ■ select min(c_age) from t_student where c_gender = '女';

      5>count 统计记录总数

          ■ select count(*) from t_student;

          ■ select count(*) from t_student where c_gender = '女';

      6>group_concat() 拼接分组中的数据

  <12>分组group by

      分组就是将相同数据放到一起进行处理。 单纯的分组是没有意义的,需要配合聚合函数一起使用。

      group by的含义:将查询结果按照1个或多个字段进行分组,字段值相同的为一组

      group by可用于单个字段分组,也可用于多个字段分组

      语法: select 分组的字段名,聚合函数... from 表名 group by 分组字段名 having 分组后的条件

      注意:

          ■ 在执行 group by 分组时,select 后只能有被分组的字段,不允许有其它字段,除非这些字段在聚合函数中

              查询显示的字段必须和分组的字段相同

          ■ 分组一般配合聚合函数使用,做数据统计功能

          ■ 分组后如果需要设置条件要使用 having 指定

      1>单字段分组

          ■ select c_gender from t_student group by c_gender;

      2>多字段分组(了解)

          ■ 可以对多个字段进行分组,作用同上,需要注意的是多字段时,只有对应字段完全相同,才能分为同一组

          ■  select c_gender,c_address from t_student group by c_gender,c_address;

      3>group by + group_concat()

          ■ group_concat(字段名)可以作为一个输出字段来使用,表示分组之后,根据分组结果,使用group_concat()来放置每一组的某字段的值的sel集合

          ■ 作用:根据分组结果,使用group_concat()来获取分组中指定字段的集合

          ■ 语法:group_concat(字段名)

              select c_gender,group_concat(c_name) from t_student group by c_gender;

      4>分组和聚和函数使用

          ■ 单纯的使用分组并没有实际意义,需要使用聚合函数对数据进行处理。

              select c_gender,max(c_age),min(c_age),sum(c_age),avg(c_age),count(*) from t_student group by c_gender;

              select c_gender,max(c_age),min(c_age),sum(c_age),avg(c_age),count(c_age) from t_student group by c_gender;

      5>having 作用和 where 类似,用来对分组数据进行筛选

          ■ 注意having只能配合分组使用

          ■ where 是对 form 表 中取数据时进行筛选

          ■ having 是对 group by 分组后的数据进行筛选

          ■ 因为在执行顺序上,在执行 where 时,分组还没有执行,得先根据 where 的条件取出数据,才能去取出的数据进行分组。

              select c_gender,group_concat(c_name) from t_student group by c_gender having c_gender = '女';

              select c_gender,group_concat(c_name) from t_student where c_age > 50 group by c_gender having c_gender = '女';

      6>分组汇总(无大用,了解即可)

          ■ 作用:会在分组下方,加一行,显示汇总

          ■ 语法:with rollup

              select c_gender from t_student group by c_gender with rollup;

              select c_gender,count(*) from t_student group by c_gender with rollup;

2.5.4 多表查询数据

在数据库操作中,数据往往不是存在一张表中的,同一个项目中,根据设计范式,数据可能分散在不同的多张表中,这时查询数据时,就需要多表查询。

  <1>普通多表查询(无意义)

      作用:直接将表放在from后面,进行读取。

      语法:select 表名.字段 ... from 表名1,表名2...

          ■  select * from t_student,t_class;

      这种查询方式没有任何意义。 在查询时,数据库会将表1中的数据逐条和表2中的所有数据连接,组成一条新记录。 查询的结果为 M * N 条,实际就是笛卡尔积结果。

  <2>多表查询连接条件

      在多表个表进行查询时,表与表之间应该是有有关系的,一般会以外键的形式来建立表间的关系。 查询时按照条件建立记录的匹配规则。 比如学生表中保存了学生的信息和所在班级的ID,班级表中保存了班级的信息。 在查询学生的班级信息时,可以通过学生表中的班级ID和班级表中的ID匹配进行查询

      select t_student.c_name,t_class.c_name  from t_student,t_class where t_student.c_class_id = t_class.c_id;

  <3>内连接查询(交集)

      作用:查询的结果为两个表匹配到的数据,内连接指定连接条件取两表的交集

      语法:select * from 表1 inner join 表2 on 表1.列 运算符 表2.列

      数据库默认的连接方式就是内连接查询,inner join 可以不显示的写出来。 不指定连接条件时,实际就是普通多表连接,会以笛卡尔积的形式进行连接。 所以在连接时,必须要给定连接条件。 连接条件使用 on 进行指定。尽量不要使用 where,where在其它连接方式时,指定的连接条件无效。

          ■ select ts.c_name, tc.c_name from t_student as ts inner join t_class tc on ts.c_class_id = tc.c_id;

  <4>左连接查询

      作用:查询的结果为根据左表中的数据进行连接,如果右表中没有满足条件的记录,则连接空值。

      注意:连接条件只能使用 on 指定

      语法: select * from 表1 left join 表2 on 表1.列 运算符 表2.列

          ■ select ts.c_name, tc.c_name from t_student as ts left join t_class tc on ts.c_class_id = tc.c_id;

  <5>右连接查询

      作用:查询的结果为根据右表中的数据进行连接,如果左表中没有满足条件的记录,则连接空值。

      注意:连接条件只能使用 on 指定

      语法: select * from 表1 right join 表2 on 表1.列 运算符 表2.列

          ■ select ts.c_name, tc.c_name from t_student as ts right join t_class tc on ts.c_class_id = tc.c_id;

      在实际工作中,右连接使用的非常少,因为左连接完全可以替代右连接,在连接过程中,只需要调整表的顺序即可。

  <6>子查询

      作用:在一个 select 语句中,嵌入了另外一个 select 语句, 那么被嵌入的 select 语句称之为子查询语句,子查询语句是一个可以独立执行的查询语句

      语法: select * from 表1 where 条件 运算符 (select 查询)

  外部那个select语句则称为主查询

  主查询和子查询的关系

          ■ 子查询是嵌入到主查询中

          ■ 子查询是辅助主查询的,要么充当条件,要么充当数据源

          ■ 子查询是可以独立存在的语句,是一条完整的 select 语句

  1>标量子查询

      作用:子查询返回的结果是一个数据(一行一列)

      语法:主查询 where 条件 比较运算符 (列子查询)

              查询班级中年龄大于平均年龄的学生信息

              查询班级学生平均年龄

              查询大于平均年龄的学生

              select * from t_student where c_age > (select avg(c_age) from t_student);

  2>列级子查询

      作用:子查询返回的结果是一列(一列多行)

      语法:主查询 where 条件 in (列子查询)

              查询所有学生所在班级的班级名称

              找出学生表中所有的班级 id

              找出班级表中对应的名字

              select * from t_class where c_id in (select c_class_id from t_student);

  3>行级子查询

      作用:子查询返回的结果是一行(一行多列)

      语法:主查询 where (字段1,2,...) = (行子查询)

              查找班级年龄最大,所在班号最小的的学生

              找出最大年龄和最小班号

              找出年龄和班号满足条件的学生

              select * from t_student where(c_age,c_class_id) = (select max(c_age),min(c_class_id) from t_student);

  <7>自连接查询

      作用:在查询数据时,只有一张表,查询时使用自己连接自己。

      语法: select * from 表1 inner join 表2 on 表1.列 运算符 表2.列 where 条件

  为什么需要自连接

      设计表结构来存储 全国 所有的省份和 全国所有的市

      设计省信息的表结构provinces

      id 省的编号

      ptitle 省名称

      设计市信息的表结构citys

      id 市编号

      ctitle 市名称

      proid 市所属的省的编号

  citys表的proid表示城市所属的省,对应着provinces表的id值

  将两个表合为一个

  定义表areas,结构如下

          ■ id

          ■ atitle

          ■ pid

      关于这个表的说明:

          ■ 因为省没有所属的省份,所以可以填写为null

          ■ 城市所属的省份pid,填写省所对应的编号id

          ■ 这就是自关联,表中的某一列,关联了这个表中的另外一列,但是它们的业务逻辑含义是不一样的,城市信息的pid引用的是省信息的id

          ■ 在这个表中,结构不变,可以添加区县、乡镇街道、村社区等信息

  areas表和自身进行连接这种形式的连接 就成为自连接。

  创建areas表的语句如下:

      注意,表所在的数据库字符集必须是utf8的,如果不是会导入数据出错

          ■ create table areas(aid int primary key,atitle varchar(20),pid int);

  从sql文件中导入数据

      source areas.sql;

  查询一共有多少个省

      select count(*) from areas where pid is null;

  例1:查询省的名称为“山西省”的所有城市

      select city.* from areas as city inner join areas as province on city.pid=province.aid where province.atitle='山西省';

  例2:查询市的名称为“广州市”的所有区县

      select dis.* from areas as dis inner join areas as city on city.aid=dis.pid where city.atitle='广州市';

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

推荐阅读更多精彩内容