zoukankan      html  css  js  c++  java
  • 数据库03

    本篇目录

    • 1.自关联
    • 2.子查询
    • 3.子查询中特定关键字使用
    • 4.查询演练
    • 5.数据分表

    1.自关联

    设计省信息的表结构provinces

    • id
    • ptitle

    设计市信息的表结构citys

    • id
    • ctitle
    • proid

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

    问题:能不能将两个表合成一张表呢?

    思考:观察两张表发现,citys表比provinces表多一个列proid,其它列的类型都是一样的

    意义:存储的都是地区信息,而且每种信息的数据量有限,没必要增加一个新表,或者将来还 要存储区、乡镇信息,都增加新表的开销太大

    答案:定义表areas,结构如下

    • id
    • atitle
    • pid

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

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

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

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

    准备数据:

    create table areas(
    aid int primary key,
    atitle varchar(20),
    pid int
    );
    insert into areas
    values ('130000', '河北省', NULL),
    ('130100', '石家庄市', '130000'),
    ('130400', '邯郸市', '130000'),
    ('130600', '保定市', '130000'),
    ('130700', '张家口市', '130000'),
    ('130800', '承德市', '130000'),
    ('410000', '河南省', NULL),
    ('410100', '郑州市', '410000'),
    ('410300', '洛阳市', '410000'),
    ('410500', '安阳市', '410000'),
    ('410700', '新乡市', '410000'),
    ('410800', '焦作市', '410000');

    例1:查询一共有多少个省

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

    例2:查询河南省的所有城市

    select
     *
    from
     areas as p
    inner join areas as c on c.pid=p.aid
    where
     p.atitle='河北省';

    添加区县数据

    insert into areas values
    ('410101', '中原区', '410100'),
    ('410102', '二七区', '410100'),
    ('410103', '金水区', '410100');

    例3:查询郑州市的所有区县

    select
     *
    from
     areas as c
    inner join areas as a on a.pid=c.aid
    where
     c.atitle='郑州市';

    例4:查询河南省的所有区县

    select
     *
    from
     areas as p
    left join areas as c on c.pid=p.aid
    left join areas as a on a.pid=c.aid
    where
     p.atitle='河南省'

    总结子查询

    01.数据有上下关系

    02.商城的商品分类

    03.在一张表中存储了所有的数据 

    2.子查询

    一个 select 语句中,嵌入了另外一个 select 语句, 那么被嵌入的 select 语句称之为子查询语句

    子查询要用小括号括起来,括号里面是子查询,括号外面是主查询。

    主查询

    主要查询的对象,第一条 select 语句

    主查询和子查询的关系

    • 子查询是嵌入到主查询中
    • 子查询是辅助主查询的,要么充当条件,要么充当数据源
    • 子查询是可以独立存在的语句,是一条完整的 select 语句

    子查询分类

    • 标量子查询: 子查询返回的结果是一个数据(一行一列)    充当条件
    • 列子查询: 返回的结果是一列(一列多行)     充当条件
    • 行子查询: 返回的结果是一行(一行多列)     充当条件
    • 表级子查询: 返回的结果是多行多列    充当数据源

    01.标量子查询(= 等号,或者>, <

    一行一列 = 一个值

    例1:查询班级学生的平均年龄

    查询班级学生平均年龄

    select avg(age) from students

    查询大于平均年龄的学生

    select * from students where age > 21.4167
    select * from students where age > (select avg(age) from students);

    例2:查询王昭君的成绩,要求显示成绩

    学生表中查询王昭君的学号

    select studentNo from students where name = '王昭君'

    成绩表中根据学号查询成绩

    select * from scores where studentNo = '001'
    select * from scores where studentNo = (select studentNo from students where name = '王昭君')

    02.列级子查询(in)

    一列多行 = 多个值

    例3:查询18岁的学生的成绩,要求显示成绩

    学生表中查询18岁的学生的学号

    select studentNo from students where age=18

    成绩表中根据学号查询成绩

    select * from scores where studentNo in ('002','006')
    select * from scores where studentNo in (select studentNo from students where age=18)

    03.行级子查询(用的不多

    一行多列

    例4:查询男生中年龄最大的学生信息

    select * from students where sex='' and age=(select max(age) from students)
    select * from students where (sex,age)=('',30)
    select * from students where (sex,age) = (select sex,age from students where sex='' o
    rder by age desc limit 1)

    04.表级子查询,(可以用多个标量子查询)

    多行多列

    例5:查询数据库和系统测试的课程成绩

    select
     *
    from
     scores s
    inner join
     (select * from courses where name in ('数据库','系统测试')) c
    on s.courseNo = c.courseNo

    除了表级子查询,其他子查询都是充当条件的。

    表级子查询是充当数据源的。

    把结果当数据源的

    01. 用括号括起来

    02. 起别名,在括号外

    在from 或者 inner join后可以跟或者结果

    3.子查询中特定关键字使用

    in 范围

    格式: 主查询 where 条件 in (列子查询)  

    any | some 任意一个

    格式: 主查询 where 列 = any (列子查询)

    在条件查询的结果中匹配任意一个即可, =any|some 等价于  in,

    !=any|some  没有意义,虽然没有报错,可以显示

    >any或者>some  大于其中任何一个,大于最小的  18

    select * from students where age >any (select age from students where age between 18 and 20);

    <any或者<some  小于其中任何一个,小于最大的  20

    select * from students where age <any (select age from students where age between 18 and 20);

    all

    格式: 主查询 where 列 = all(列子查询) : 等于里面所有,没有意义

    格式: 主查询 where 列 <>all(列子查询) : 大于所有,或者小于所有。

    <all(18,19,20)     <最小的18

    select * from students where age <all (select age from students where age between 18 and 20);

    >all(18,19,20)     >最大的20

    select * from students where age >all (select age from students where age between 18 and 20);

    !=all    除去这些

    select * from students where age !=all (select age from students where age between 18 and 20);

    4.查询演练

    准备数据

    create table goods(
     id int unsigned primary key auto_increment,
     name varchar(150),
     cate varchar(40),
     brand_name varchar(40),
     price decimal(10,3) default 0,
     is_show bit default 1,
     is_saleoff bit default 0
    );
    insert into goods values(0,'r510vc 15.6英寸笔记本','笔记本','华硕','3399',default,default);
    insert into goods values(0,'y400n 14.0英寸笔记本电脑','笔记本','联想','4999',default,default);
    insert into goods values(0,'g150th 15.6英寸游戏本','游戏本','雷神','8499',default,default);
    insert into goods values(0,'x550cc 15.6英寸笔记本','笔记本','华硕','2799',default,default);
    insert into goods values(0,'x240 超极本','超级本','联想','4999',default,default);
    insert into goods values(0,'u330p 13.3英寸超极本','超级本','联想','4299',default,default);
    insert into goods values(0,'svp13226scb 触控超极本','超级本','索尼','7999',default,default);
    insert into goods values(0,'ipad mini 7.9英寸平板电脑','平板电脑','苹果','1998',default,default);
    insert into goods values(0,'ipad air 9.7英寸平板电脑','平板电脑','苹果','3388',default,default);
    insert into goods values(0,'ipad mini 配备 retina 显示屏','平板电脑','苹果','2788',default,default);
    insert into goods values(0,'ideacentre c340 20英寸一体电脑 ','台式机','联想','3499',default,default);
    insert into goods values(0,'vostro 3800-r1206 台式电脑','台式机','戴尔','2899',default,default);
    insert into goods values(0,'imac me086ch/a 21.5英寸一体电脑','台式机','苹果','9188',default,default);
    insert into goods values(0,'at7-7414lp 台式电脑 linux )','台式机','宏碁','3699',default,default);
    insert into goods values(0,'z220sff f4f06pa工作站','服务器/工作站','惠普','4288',default,default);
    insert into goods values(0,'poweredge ii服务器','服务器/工作站','戴尔','5388',default,default);
    insert into goods values(0,'mac pro专业级台式电脑','服务器/工作站','苹果','28888',default,default);
    insert into goods values(0,'hmz-t3w 头戴显示设备','笔记本配件','索尼','6999',default,default);
    insert into goods values(0,'商务双肩背包','笔记本配件','索尼','99',default,default);
    insert into goods values(0,'x3250 m4机架式服务器','服务器/工作站','ibm','6888',default,default);
    insert into goods values(0,'hmz-t3w 头戴显示设备','笔记本配件','索尼','6999',default,default);
    insert into goods values(0,'商务双肩背包','笔记本配件','索尼','99',default,default);

    查询演练

    求所有电脑产品的平均价格,并且保留两位小数(round())

    select round(avg(price),2) as avg_price from goods;

    查询所有价格大于平均价格的商品,并且按价格降序排序

    select id,name,price from goods
    where price > (select round(avg(price),2) as avg_price from goods)
    order by price desc;

    查询类型为'超极本'的商品价格

    select price from goods where cate = '超级本';

    查询价格大于或等于"超级本"价格的商品,并且按价格降序排列

    select id,name,price from goods
    where price >= any(select price from goods where cate = '超级本')
    order by price desc;

    分表之后可以查

    select id,name,price from goods
    where price >= any(select price from goods where cate = (select cate_id from goods_cates where cate_name='超级本'))
    order by price desc;

    = any 或者 =some 等价 in

    select id,name,price from goods
    where price in (select price from goods where cate = '超级本')
    order by price desc;

    !=all 等价于 not in

    select id,name,price from goods
    where price not in (select price from goods where cate = '超级本')
    order by price desc;

    5.数据分表

    创建“商品分类”表

    create table if not exists goods_cates(
     cate_id int unsigned primary key auto_increment,
     cate_name varchar(40)
    );

    查询goods表的所有记录,并且按"类别"分组

    select cate from goods group by cate;

    将分组结果写入到goods_cates数据表

    通过insert into ...  select ...   查询的数据插入表中

    insert into goods_cates (cate_name) select cate from goods group by cate;

    通过goods_cates数据表来更新goods表

    通过update  连接查询  set ....        更新的时候连接查询,更新表中的字段

    update goods as g inner join goods_cates as c on g.cate = c.cate_name
    set cate = cate_id;

    小技巧:可以先把update写成select ,写好sql语句换成update 

    通过create table  新表明(新字段)select 旧字段     来创建数据表并且同时写入记录,一步到位

    create table goods_brands (
     brand_id int unsigned primary key auto_increment,
     brand_name varchar(40)) select brand_name from goods group by brand_name;

    注意:新字段和旧字段名称相同,插入相同字段名称数据

    如果不相同再创建旧字段名称和插入数据

    小案例:拷贝一份goods表 

    create table goods_back SELECT * from goods;

    通过goods_brands数据表来更新goods数据表

    update goods as g inner join goods_brands as b on g.brand_name = b.brand_name
    set g.brand_name = b.brand_id;

    查看 goods 的数据表结构,会发现 cate 和 brand_name对应的类型为 varchar 但是存储的都 是字符串

    修改数据表结构,把cate字段改为cate_id且类型为int unsigned,把brand_name字段改为 brand_id且类型为int unsigned

    分别在 good_scates 和 goods_brands表中插入记录

    insert into goods_cates(cate_name) values ('路由器'),('交换机'),('网卡');
    insert into goods_brands(brand_name) values ('海尔'),('清华同方'),('神舟');

    在 goods 数据表中写入任意记录

    insert into goods (name,cate_id,brand_id,price)
    values('LaserJet Pro P1606dn 黑白激光打印机','12','4','1849');

    查询所有商品的详细信息 (通过左右链接来做)

    select * from goods left join goods_cates on goods.cate_id=goods_cates.id
    inner join goods_brands on goods.brand_id=goods_brands.id

    显示没有商品的品牌(通过右链接+子查询来做) -- 右链接

    select * from goods right join goods_brands on goods.brand_id = goods_brands.id where goods.name is null;

    分表后我的字段没改,可以用下面的

    select * from goods right join goods_brands on goods.brand_name=goods_brands.brand_id where goods.name is null;

    -- 子查询

    select * from goods_brands where id not in (select DISTINCT brand_id from goods)

    补充:

    例1:多表连接查询

    select   表1 

    inner join  表2

    inner join  表3   这里可以和表1或表2相同字段连接

    例2:多张表查询一般都是:

    01.连接查询   02子查询   03连接查询+子查询

  • 相关阅读:
    URL中的特殊字符 + % # & = ? /
    mvc 前端显示文本中的html标签处理
    URL中#号(井号)的作用
    自定义配置节 Section
    vshost.exe.config与.exe.config ;Debug目录与Release目录;bin目录与obj目录
    在MVC过滤器中获取触发的Controller、Action、参数 等
    js设置全局变量 ajax中赋值
    批处理 安装、卸载 window service
    [摘]HttpContext, HttpRequest, HttpResponse, HttpRuntime, HttpServerUtility
    摘要:ASP.NET的路由
  • 原文地址:https://www.cnblogs.com/zhangyangcheng/p/12200801.html
Copyright © 2011-2022 走看看