mysql-复习

mysql复习

二 基础知识:

1.数据库的连接

mysql -u -p -h

-u 用户名

-p 密码

-h host主机

2:库级知识

2.1 显示数据库: show databases;

2.2 选择数据库: use dbname;

2.3 创建数据库: create database dbname charset utf8;

2.3 删除数据库: drop database dbname;

3: 表级操作:

3.1 显示库下面的表

show tables;

会把视图页查出来

3.11 查看表结构

Desc 表名/视图名

3.2 查看表的结构:

desc tableName;

3.3 查看表的创建过程:

show create table tableName;

3.32 改表名

Rename table t1 to t2

3.33 删除表

Drop table t1

Drop view v1 删除视图

3.4 创建表:

 create table tbName (

列名称1 列类型 [列参数] [not null default ],

....列2...

....

列名称N 列类型 [列参数] [not null default ]

)engine myisam/innodb charset utf8/gbk

3.4的例子:

create table user (

id int auto_increment,

name varchar(20) not null default '',

age tinyint unsigned not null default 0,

index id (id)

)engine=innodb charset=utf8;

注:innodb是表引擎,也可以是myisam或其他,但最常用的是myisam和innodb,

charset 常用的有utf8,gbk;

为什么建表时,加not null default '' / default 0

答:不想让表中出现null值.


为什么不想要的null的值

答:

    不好比较,null是一种类型,比较时,只能用专门的is null 和 is not null来比较.

碰到运算符,一律返回null

效率不高,影响提高索引效果.

修改表的语法

一张表,创建完毕,有了N列.

之后还有可能要增加或删除或修改列


Alter table 表名 add 列名称 列类型 列参数; [加的列在表的最后]

例: alter table m1 add birth date not null default '0000-00-00';

Alter table 表名 add 列名称 列类型 列参数 after 某列 [把新列加在某列后]

例: alter table m1 add gender char(1) not null default '' after username;

Alter table 表名 add 列名称 列类型 列参数 first [把新列加在最前面]

例: alter table m1 add pid int not null default 0 first;

删除列:

Alter table 表名 drop 列名

修改列类型:

Alter table 表名 modify 列名 新类型 新参数

例:alter table m1 modify gender char(4) not null default '';

修改列名及列类型

Alter table 表名 change 旧列名 新列名 新类型 新参数

例:alter table m1 change id uid int unsigned;

作业: 让我们建一个电子商城, 如何来设计商品表.

再把商城表的字段,一个个删掉,再一个个加上.

并穿插改列操作.

??如果列类型改变了,导致数据存不下怎么办?

比如,int 改成smallint列. 如果不匹配,数据将会丢失,或者在mysql的strict_mode下,修改不了.


4.1

主键 primary key

此列不重复,能区分每一行

注意:一张表 只能1 列为auto_increment 且此列必须加索引


视图 view

在查询中,我们经常把查询结果 当成临时表来看.

View是什么? View可以看一张虚拟表. 是表通过某种运算得到的一个投影.

                         

既然视图只是表的某种查询的投影,所以主要步骤在于查询表上.

查询的结果命名为视图就可以了.

视图的定义:

视图是由查询结果形成的一张虚拟表.viem是sql的查询结果

视图的创建语法:

Create view 视图名 as select 语句;

视图的删除语法:

Drop view 视图名

为什么要视图?

答:

1:可以简化查询

2: 可以进行权限控制

把表的权限封闭,但是开放相应的视图权限,视图里只开放部分数据

3: 大数据分表时可以用到

比如,表的行数超过200万行时,就会变慢,

可以把一张的表的数据拆成4张表来存放.

News表

Newsid, 1,2,3,4

News1,news2,news3,news4表

把一张表的数据分散到4张表里,分散的方法很多,

最常用可以用id取模来计算.

Id%4+1 = [1,2,3,4]

比如 $_GET['id'] = 17,

17%4 + 1 = 2, $tableName = 'news'.'2'

Select * from news2 where id = 17;

还可以用视图, 把4张表形成一张视图

Create view news as select from n1 union select from n2 union.........

视图的修改

Alter view 视图名 as select xxxxxx

视图是表的一个影子.

表与视图,数据变化时的相互影响问题.


视图与表的关系

视图是表的查询结果,自然表的数据改变了,影响视图的结果.

视图改变了呢?

0: 视图增删改也会影响表

1: 但是,视图并是总是能增删改的.

视图某种情况下,是可以修改的.

要求: 视图的数据和表的数据 11对应. 就像函数的映射.

表-->推出视图对应的数据

视图-->推出表对应的数据

对于视图insert还应注意,

视图必须包含表中没有默认值的列.

以这个例子而言,平均价来自于多行的的shop_price的计算结果.

如果pj列的值的变子,映射过去,到底修改哪几行shop_price?


视图的algorithm

Algorithm = merge/ temptable/ undefined

Merge: 当引用视图时,引用视图的语句与定义视图的语句合并.

Temptable:当引用视图时,根据视图的创建语句建立一个临时表

Undefined:未定义,自动,让系统帮你选.

Merge,意味着视图只是一个规则,语句规则, 当查询视图时,

把查询视图的语句(比如where那些)与创建时的语句where子句等合并,分析.

形成一条select 语句.

例: 创建视图的语句:

mysql> create view g2 as select goods_id,cat_id,goods_name,shop_price from goods where shop_price>2000

查询视图的语句:

select * from g2 where shop_price < 3000;

最终执行的语句:

select goods_id,cat_id,goods_name,shop_price from goods where shop_price > 2000 and shop_price < 3000

而temptable是根据创建语句瞬间创建一张临时表,

然后查询视图的语句从该临时表查数据.

create algorethm=temptable view g2 as select goods_id,cat_id,goods_name,shop_price from goods where shop_price > 2000

查询视图的语句:

select * from g2 where shop_price < 3000;

最终执行的2句话: 取数据并放在临时表,然后去查临时表.

Select goods_id,cat_id,goods_name,shop_price from goods where shop_price > 2000;

========> temptable

再次查临时表

Select * from temptable where shop_price< 3000

列类型学习

mysql三大列类型

数值型

整型

Tinyint/ smallint/ mediumint/int/ bigint(M) unsigned zerofill

整型系列所占字节与存储范围的关系.

定性: 占字节越多,存储范围越大.

下图: 是具体的数字分析

整型系统的可选参数 : XXint(M) unsigned zerofill

例: age tinyint(4) unsigned ,或者 stunum smallint(6) zerofill;

Unsigned: 代表此列为无符号类型, 会影响到列的存储范围. (范围从0开始)

(不加unsinged, 则该列默认是有符号类型,范围从负数开始)

Zerofill: 代表0填充, 即: 如果该数字不足参数M位, 则自动补0, 补够M位.

1: 如果没有zerofill属性, 单独的参数M,没有任何意义.

2:如果设置某列为zerofill,则该列已经默认为 unsigned,无符号类型.


小数型

Float(M,D),decimal(M,D)

M叫"精度" ---->代表"总位数",而D是"标度",代表小数位.(小数右边的位数)

浮点数占多大的空间呢

答: float 能存10^38 ,10^-38

如果M<=24, 点4个字节,否则占8字节

用来表示数据中的小数,除了float---浮点.

还有一种叫定点decimal,定点是把整数部分, 和小数部分,分开存储的.

比float精确,他的长度是变化的.

空间上的区别:

Float(M,D), M<=24, 4个字节, 24

Decimal () ,变长字节.

区别: decimal比float精度更高, 适合存储货币等要求精确的数字,

:


字符串型

Char(M)

Varchar(M)

Text 文本类型

日期时间类型

Date 日期

Time 时间

Datetime 时间时间类型

Year 年类型

Mysql 字符串类型

Char 定长类型

Char(M) , M 代表宽度, 0<=M<=255之间

例:Char(10) ,则能输入10个字符. 但只写一个也算10个字符的宽度

Varchar 变长类型

Varchar(M), M代表宽度, 0<=M<=65535(以ascii字符为例,utf822000左右)

类型

类型

宽度

可存字符

实存字符(i<=M)

实占空间

利用率

Char

M

M

i

M

i/M <= 100%

Varchar

M

M

i

i字符+(1-2)字节

i/(i+1-2) < 100%

0000000000

00\0\0\0\0\0 (char型,如果不够M个字符,内部用空格补齐,取出时再把右侧空格删掉)

注:这意味着,如果右侧本身有空格,将会丢失.

Varchar(10)

[2]张三

[3]二麻子

[4]司马相如

Char(8)

00000000

'Hello '

'hello '

Char(M)如何占据M个字符宽度?

答: 如果实际存储内容不足M个,则后面加空格补齐.

取出来的时候, 再把后面的空格去掉.(所以,如果内容最后有空格,将会被清除).

速度上: 定长速度快些

注意: char(M),varchar(M)限制的是字符,不是字节.

即 char(2) charset utf8, 能存2个utf8字符. 比如'中国'char与varchar型的选择原则:

1:空间利用效率, 四字成语表, char(4),

个人简介,微博140字, varchar(140)

2:速度

用户名: char

Char 与 varchar相关实验

Text : 文本类型,可以存比较大的文本段,搜索速度稍慢.

因此,如果不是特别大的内容,建议用char,varchar来代替.

Text 不用加默认值 (加了也没用).

Blob,是二进制类型,用来存储图像,音频等二进制信息.

意义: 2进制,0-255都有可能出现.

Blob在于防止因为字符集的问题,导致信息丢失.

比如:一张图片中有0xFF字节, 这个在ascii字符集认为非法,在入库的时候,被过滤了.


日期时间类型

Year 年(1字节) 95/1995, [1901-2155],

在insert时,可以简写年的后2位,但是不推荐这样.

[00-69] +2000

[70-99] + 1900,

即: 填2位,表示 1970 - 2069

Date 日期 1998-12-31

范围: 1000/01/01 ,9999/12/31

Time 时间 13:56:23

范围: -838:59:59 -->838:59:59


datetime 时期时间 1998-12-31 13:56:23

范围: 1000/01//01 00:00:00 ---> 9999:12:31 23:59:59

timestamp

时间戳:

是1970-01-01 00:00:00 到当前的秒数.

一般存注册时间,商品发布时间等,并不是用datetime存储,而是用时间戳.

因为datetime虽然直观,但计算不便.


3.5 修改表

3.5.1 修改表之增加列:

alter table tbName

add 列名称1 列类型 [列参数] [not null default ] #(add之后的旧列名之后的语法和创建表时的列声明一样)

3.5.2 修改表之修改列

alter table tbName

change 旧列名 新列名 列类型 [列参数] [not null default ]

(注:旧列名之后的语法和创建表时的列声明一样)

3.5.3 修改表之减少列:

alter table tbName

drop 列名称;

3.5.4 修改表之增加主键

alter table tbName add primary key(主键所在列名);

例:alter table goods add primary key(id)

该例是把主键建立在id列上

3.5.5 修改表之删除主键

alter table tbName drop primary key;

3.5.6 修改表之增加索引

alter table tbName add [unique|fulltext] index 索引名(列名);

3.5.7 修改表之删除索引

alter table tbName drop index 索引名;

3.5.8 清空表的数据

truncate tableName;

4:列类型讲解

列类型:

整型:tinyint (0~255/-128~127) smallint (0~65535/-32768~32767) mediumint int bigint (参考手册11.2)

参数解释:

unsigned 无符号(不能为负) zerofill 0填充 M 填充后的宽度

举例:tinyint unsigned;

tinyint(6) zerofill;

数值型

浮点型:float double

格式:float(M,D) unsigned\zerofill;

字符型

char(m) 定长

varchar(m)变长

text

列 实存字符i 实占空间 利用率

char(M) 0<=i<=M M i/m<=100%

varchar(M) 0<=i<=M i+1,2 i/i+1/2<100%

year YYYY 范围:1901~2155. 可输入值2位和4位(如98,2012)

日期时间类型 date YYYY-MM-DD 如:2010-03-14

time HH:MM:SS 如:19:26:32

datetime YYYY-MM-DD HH:MM:SS 如:2010-03-14 19:26:32

timestamp YYYY-MM-DD HH:MM:SS 特性:不用赋值,该列会为自己赋当前的具体时间

5:增删改查基本操作

5.1 插入数据

insert into 表名(col1,col2,……) values(val1,val2……); -- 插入指定列

insert into 表名 values (,,,,); -- 插入所有列

insert into 表名 values -- 一次插入多行

(val1,val2……),

(val1,val2……),

(val1,val2……);

5.3修改数据

update tablename

set

col1=newval1,

col2=newval2,

...

...

colN=newvalN

where 条件;

5.4,删除数据 delete from tablenaeme where 条件;

5.5, select 查询

select count(*) from 表名, 查询的就是绝对的行数,哪怕某一行所有字段全为NULL,也计算在内.

而select couht(列名) from 表名,

查询的是该列不为null的所有行的行数.

语法:

SELECT selection_list /*要查询的列名称*/

FROM table_list /*要查询的表名称*/

WHERE condition /*行条件*/

GROUP BY grouping_columns /*对结果分组*/

HAVING condition /*分组后的行条件*/

ORDER BY sorting_columns /*对结果分组*/

LIMIT offset_start, row_count /*结果限定*/

(1) 条件查询 where a. 条件表达式的意义,表达式为真,则该行取出

b. 比较运算符 = ,!=,< > <= >=

c. like , not like ('%'匹配任意多个字符,'_'匹配任意单个字符)

‘诺基亚_’ 诺基亚加一个字符

‘诺基亚%’ 诺基亚加任意多个字符

in , not in , between and

d. is null , is not null 表示是不是null, 不能用where ...=null

(2) 分组 group by

一般要配合5个聚合函数使用:max,min,sum,avg,count

Select avg(shop_price) from user group by cat_id 分组 每个cat_id的平均

..... 同理

(3) 筛选 having

Select goods_id, (market_price-shop_price) as sheng from goods

Where 1

Having sheng >200; 筛选出差价大于200的

不能简单地写成where sheng>200

 

注意,WHERE是对分组前记录的条件,如果某行记录没有满足WHERE子句的条件,那么这行记录不会参加分组;而HAVING是对分组后数据的约束。

(4) 排序 order by

Select goods_id from ecs_goods order by shop_price desc; 降序排列

Asc 或者不写 ,就是升序

Select goods_id from ecs_goods order by cat_id asc, shop_price desc; 先按cat_id排,里面按照shop_price排

(5) 限制 limit 跳过前面n条取x条

Select goods_name from goods order by shop_price desc limit 0,3偏移0行取三行

注:偏移量为0可以不写,但不推荐

6: 连接查询

6.1, 左连接

.. left join .. on

table A left join table B on tableA.col1 = tableB.col2 ;

例句:

select 列名 from table A left join table B on tableA.col1 = tableB.col2

2. 右链接: right join

3. 内连接: inner join

左右连接都是以在左边的表的数据为准,沿着左表查右表.

内连接是以两张表都有的共同部分数据为准,也就是左右连接的数据之交集.

左右与内不同的是,内遇到是null的就不取了,而左右还是要取

左连接的语法:

假设A表在左,不动,B表在A表的右边滑动.

A表与B表通过一个关系来筛选B表的行.

语法:

A left join B on 条件 条件为真,则B表对应的行,取出

A left join B on 条件

这一块,形成的也是一个结果集,可以看成一张表 设为C

既如此,可以对C表作查询,自然where,group ,having ,order by ,limit 照常使用

问:C表的可以查询的列有哪些列?

答: A B的列都可以查

5 外键

主外键是构成表与表关联的唯一途径!

外键是另一张表的主键!例如员工表与部门表之间就存在关联关系,其中员工表中的部门编号字段就是外键,是相对部门表的外键。

我们再来看BBS系统中:用户表(t_user)、分类表(t_section)、帖子表(t_topic)三者之间的关系。

例如在t_section表中sid为1的记录说明有一个分类叫java,版主是t_user表中uid为1的用户,即zs!

例如在t_topic表中tid为2的记录是名字为“Java是咖啡”的帖子,它是java版块的帖子,它的作者是ww。

外键就是用来约束这一列的值必须是另一张表的主键值!!!

l 创建t_user表,指定uid为主键列:

CREATE TABLE t_user(

uid INT PRIMARY KEY AUTO_INCREMENT,

uname VARCHAR(20) UNIQUE NOT NULL

);

l 创建t_section表,指定sid为主键列,u_id为相对t_user表的uid列的外键:

CREATE TABLE t_section(

sid INT PRIMARY KEY AUTO_INCREMENT,

sname VARCHAR(30),

u_id INT,

CONSTRAINT fk_t_user FOREIGN KEY(u_id) REFERENCES t_user(uid)

);

l 修改t_section表,指定u_id为相对t_user表的uid列的外键:

ALTER TABLE t_section

ADD CONSTRAINT fk_t_user

FOREIGN KEY(u_id)

REFERENCES t_user(uid);

l 修改t_section表,删除u_id的外键约束:

ALTER TABLE t_section

DROP FOREIGN KEY fk_t_user;

6 表与表之间的关系

l 一对一:例如t_person表和t_card表,即人和身份证。这种情况需要找出主从关系,即谁是主表,谁是从表。人可以没有身份证,但身份证必须要有人才行,所以人是主表,而身份证是从表。设计从表可以有两种方案:

Ø 在t_card表中添加外键列(相对t_user表),并且给外键添加唯一约束;

Ø 给t_card表的主键添加外键约束(相对t_user表),即t_card表的主键也是外键。

l 一对多(多对一):最为常见的就是一对多!一对多和多对一,这是从哪个角度去看得出来的。t_user和t_section的关系,从t_user来看就是一对多,而从t_section的角度来看就是多对一!这种情况都是在多方创建外键!

l 多对多:例如t_stu和t_teacher表,即一个学生可以有多个老师,而一个老师也可以有多个学生。这种情况通常需要创建中间表来处理多对多关系。例如再创建一张表t_stu_tea表,给出两个外键,一个相对t_stu表的外键,另一个相对t_teacher表的外键。

多表查询

多表查询有如下几种:

l 合并结果集;

l 连接查询

Ø 内连接

Ø 外连接

² 左外连接

² 右外连接

² 全外连接(MySQL不支持)

Ø 自然连接

l 子查询

1 合并结果集

1. 作用:合并结果集就是把两个select语句的查询结果合并到一起!

2. 合并结果集有两种方式:

l UNION:去除重复记录,例如:SELECT * FROM t1 UNION SELECT * FROM t2;

l UNION ALL:不去除重复记录,例如:SELECT * FROM t1 UNION ALL SELECT * FROM t2。

3. 要求:被合并的两个结果:列数、列类型必须相同。

2 连接查询

连接查询就是求出多个表的乘积,例如t1连接t2,那么查询出的结果就是t1*t2。

连接查询会产生笛卡尔积,假设集合A={a,b},集合B={0,1,2},则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。可以扩展到多个集合的情况。

那么多表查询产生这样的结果并不是我们想要的,那么怎么去除重复的,不想要的记录呢,当然是通过条件过滤。通常要查询的多个表之间都存在关联关系,那么就通过关联关系去除笛卡尔积。

你能想像到emp和dept表连接查询的结果么?emp一共14行记录,dept表一共4行记录,那么连接后查询出的结果是56行记录。

也就你只是想在查询emp表的同时,把每个员工的所在部门信息显示出来,那么就需要使用主外键来去除无用信息了。

  使用主外键关系做为条件来去除无用信息

SELECT * FROM emp,dept WHERE emp.deptno=dept.deptno;

上面查询结果会把两张表的所有列都查询出来,也许你不需要那么多列,这时就可以指定要查询的列了。

SELECT emp.ename,emp.sal,emp.comm,dept.dname

FROM emp,dept

WHERE emp.deptno=dept.deptno;

还可以为表指定别名,然后在引用列时使用别名即可。

SELECT e.ename,e.sal,e.comm,d.dname

FROM emp AS e,dept AS d

WHERE e.deptno=d.deptno;

2.1 内连接

上面的连接语句就是内连接,但它不是SQL标准中的查询方式,可以理解为方言!SQL标准的内连接为:

SELECT *

FROM emp e

INNER JOIN dept d

ON e.deptno=d.deptno;

内连接的特点:查询结果必须满足条件。例如我们向emp表中插入一条记录:

  其中deptno为50,而在dept表中只有10、20、30、40部门,那么上面的查询结果中就不会出现“张三”这条记录,因为它不能满足e.deptno=d.deptno这个条件。

2.2 外连接(左连接、右连接)

外连接的特点:查询出的结果存在不满足条件的可能。

左连接:

SELECT * FROM emp e

LEFT OUTER JOIN dept d

ON e.deptno=d.deptno;

左连接是先查询出左表(即以左表为主),然后查询右表,右表中满足条件的显示出来,不满足条件的显示NULL。

这么说你可能不太明白,我们还是用上面的例子来说明。其中emp表中“张三”这条记录中,部门编号为50,而dept表中不存在部门编号为50的记录,所以“张三”这条记录,不能满足e.deptno=d.deptno这条件。但在左连接中,因为emp表是左表,所以左表中的记录都会查询出来,即“张三”这条记录也会查出,但相应的右表部分显示NULL。

2.3 右连接

右连接就是先把右表中所有记录都查询出来,然后左表满足条件的显示,不满足显示NULL。例如在dept表中的40部门并不存在员工,但在右连接中,如果dept表为右表,那么还是会查出40部门,但相应的员工信息为NULL。

SELECT * FROM emp e

RIGHT OUTER JOIN dept d

ON e.deptno=d.deptno;

连接查询心得

连接不限与两张表,连接查询也可以是三张、四张,甚至N张表的连接查询。通常连接查询不可能需要整个笛卡尔积,而只是需要其中一部分,那么这时就需要使用条件来去除不需要的记录。这个条件大多数情况下都是使用主外键关系去除。

两张表的连接查询一定有一个主外键关系,三张表的连接查询就一定有两个主外键关系,所以在大家不是很熟悉连接查询时,首先要学会去除无用笛卡尔积,那么就是用主外键关系作为条件来处理。如果两张表的查询,那么至少有一个主外键条件,三张表连接至少有两个主外键条件。

3 自然连接

大家也都知道,连接查询会产生无用笛卡尔积,我们通常使用主外键关系等式来去除它。而自然连接无需你去给出主外键等式,它会自动找到这一等式:

l 两张连接的表中名称和类型完成一致的列作为条件,例如emp和dept表都存在deptno列,并且类型一致,所以会被自然连接找到!

当然自然连接还有其他的查找条件的方式,但其他方式都可能存在问题!

SELECT * FROM emp NATURAL JOIN dept;

SELECT * FROM emp NATURAL LEFT JOIN dept;

SELECT * FROM emp NATURAL RIGHT JOIN dept;

4 子查询

子查询就是嵌套查询,即SELECT中包含SELECT,如果一条语句中存在两个,或两个以上SELECT,那么就是子查询语句了。

l 子查询出现的位置:

Ø where后,作为条件的一部分;

Ø from后,作为被查询的一条表;

l 当子查询出现在where后作为条件时,还可以使用如下关键字:

Ø any

Ø all

l 子查询结果集的形式:

Ø 单行单列(用于条件)

Ø 单行多列(用于条件)

Ø 多行单列(用于条件)

Ø 多行多列(用于表)

练习:

1. 工资高于甘宁的员工。

分析:

查询条件:工资>甘宁工资,其中甘宁工资需要一条子查询。

第一步:查询甘宁的工资

SELECT sal FROM emp WHERE ename='甘宁'

第二步:查询高于甘宁工资的员工

SELECT * FROM emp WHERE sal > (${第一步})

结果:

SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename='甘宁')

l 子查询作为条件

l 子查询形式为单行单列

2. 工资高于30部门所有人的员工信息

分析:

查询条件:工资高于30部门所有人工资,其中30部门所有人工资是子查询。高于所有需要使用all关键字。

第一步:查询30部门所有人工资

SELECT sal FROM emp WHERE deptno=30;

第二步:查询高于30部门所有人工资的员工信息

SELECT * FROM emp WHERE sal > ALL (${第一步})

结果:

SELECT * FROM emp WHERE sal > ALL (SELECT sal FROM emp WHERE deptno=30)

l 子查询作为条件

l 子查询形式为多行单列(当子查询结果集形式为多行单列时可以使用ALL或ANY关键字)

3. 查询工作和工资与殷天正完全相同的员工信息

分析:

查询条件:工作和工资与殷天正完全相同,这是子查询

第一步:查询出殷天正的工作和工资

SELECT job,sal FROM emp WHERE ename='殷天正'

第二步:查询出与殷天正工作和工资相同的人

SELECT * FROM emp WHERE (job,sal) IN (${第一步})

结果:

SELECT * FROM emp WHERE (job,sal) IN (SELECT job,sal FROM emp WHERE ename='殷天正')

l 子查询作为条件

l 子查询形式为单行多列

4. 查询员工编号为1006的员工名称、员工工资、部门名称、部门地址

分析:

查询列:员工名称、员工工资、部门名称、部门地址

查询表:emp和dept,分析得出,不需要外连接(外连接的特性:某一行(或某些行)记录上会出现一半有值,一半为NULL值)

条件:员工编号为1006

第一步:去除多表,只查一张表,这里去除部门表,只查员工表

SELECT ename, sal FROM emp e WHERE empno=1006

第二步:让第一步与dept做内连接查询,添加主外键条件去除无用笛卡尔积

SELECT e.ename, e.sal, d.dname, d.loc

FROM emp e, dept d

WHERE e.deptno=d.deptno AND empno=1006

第二步中的dept表表示所有行所有列的一张完整的表,这里可以把dept替换成所有行,但只有dname和loc列的表,这需要子查询。

第三步:查询dept表中dname和loc两列,因为deptno会被作为条件,用来去除无用笛卡尔积,所以需要查询它。

SELECT dname,loc,deptno FROM dept;

第四步:替换第二步中的dept

SELECT e.ename, e.sal, d.dname, d.loc

FROM emp e, (SELECT dname,loc,deptno FROM dept) d

WHERE e.deptno=d.deptno AND e.empno=1006

l 子查询作为表

l 子查询形式为多行多列


同学见面会:

男生表

姓名

配偶

张三

A

李四

B

王五

C

高富帅

D

郑七

E

女生表

姓名

配偶

空姐

B

大S

C

阿娇

D

张柏芝

D

林黛玉

E

宝钗

F

主持人大声说:

所有的男士,站到舞台上,带上自己的配偶,(没有的拿块牌子, 上写NULL)

思考:张三上不上舞台呢?

答:上,

问:张三没有对应的行怎么办?

答:用NULL补齐

结果如下

姓名

配偶

女生姓名

配偶

张三

A

NULL

NULL

李四

B

空姐

B

王五

C

大S

C

高富帅

D

阿娇

D

高富帅

D

张柏芝

D

郑七

E

林黛玉

E

这种情况就是 男生 left join 女生.

主持人说:所有女生请上舞台,有配偶的带着, 没有的,写个NULL补齐.

Select 女生 left join 男生 on 条件

左右连接是可以互换的

A left join B, 就等价于 B right join A

注意:既然左右连接可以互换,尽量用左连接,出于移植时兼容性方面的考虑.


内连接的特点

主持人说: 所有有配偶的男生/女生,走到舞台上来

这种情况下: 张三和宝钗都出局

姓名

配偶

女生姓名

配偶

李四

B

空姐

B

王五

C

大S

C

高富帅

D

阿娇

D

高富帅

D

张柏芝

D

郑七

E

林黛玉

E

如果从集合的角度

A inner join B

和 left join /right join的关系

答: 内连接是左右连接的交集

问题:

主持人说:所有男生/女生,走上舞台.

有配偶的,带着配偶;

没配偶的,拿牌子写NULL

即:结果是左右连接的并集

这种叫做外连接,但是,在mysql中不支持外连接


Union:合并2条或多条语句的结果

语法:

Sql1 union sql2

能否从2张表查询再union呢?

答:可以,union 合并的是"结果集",不区分在自于哪一张表.

问:取自于2张表,通过"别名"让2个结果集的列一致.

那么,如果取出的结果集,列名字不一样,还能否union.

答:可以,如下图,而且取出的最终列名,以第1条sql为准

问:union满足什么条件就可以用了?

答:只要结果集中的列数一致就可以.

问:列的类型不一样,也行吗?

答:可以,列名称未必要一致 会使用第一条sql的列名称

问: union后结果集,可否再排序呢?

答:可以的.

Sql1 union sql2 order by 字段

注意: order by 是针对合并后的结果集排的序.

如果不是union all 就会把完全相同的行合并在一起


问: 使用order by 的注意事项

如下,内层语句的desc怎么没发挥作用呢?

思考如下语句:

(SELECT goods_id,cat_id,goods_name,shop_price FROM goods WHERE cat_id = 4 ORDER BY shop_price DESC)

UNION

(SELECT goods_id,cat_id,goods_name,shop_price FROM goods WHERE cat_id = 5 ORDER BY shop_price DESC)

order by shop_price asc;

Union的子句中,不用写orderBy

Sql合并后得到的总的结果,可以orderby ,子句orderby就失去意义了

因此:内层的order by 语句单独使用,不会影响结果集,仅排序,

在执行期间,就被Mysql的代码分析器给优化掉了.

内层的order by 必须能够影响结果集时,才有意义.

比如 配合limit 使用. 如下例.

思考下个问题:

查出: 第3个栏目下,价格前3高的商品,和第4个栏目下,价格前2高的商品.

用union来完成

这一次:内层的order by 发挥了作用,因为有limit ,order 会实际影响结果集,有意义.

如果Union后的结果有重复(即某2行,或N行,所有的列,值都一样),怎么办?

答:这种情况是比较常见的,默认会去重.

问:如果不想去重怎么办?

答: union all


7 子查询

where 型子查询:内层sql的返回值在where后作为条件表达式的一部分

如果 where 列=(内层sql),则内层sql返回的必是单行单列,单个值

如果 where 列 in (内层sql), 则内层sql只返回单列,可以多行.

例句: select * from tableA where colA = (select colB from tableB where ...);

每个栏目下最想的商品

from 型子查询:内层sql查询结果,作为一张表,供外层的sql语句再次查询

例句:select * from (select * from ...) as tableName where ....

9. 存储引擎

Show table status where name=’t11’

就可以查看表的信息 可以看到引擎

存储引擎 engine=1\2

1 Myisam 速度快 不支持事务 回滚

2 Innodb 速度慢 支持事务,回滚

字符集与乱码问题

客服端sql编码 character_set_client

服务器转化后的sql编码 character_set_connection

服务器返回给客户端的结果集编码 character_set_results

快速把以上3个变量设为相同值: set names 字符集

➕页面本身 ... 这几步设完就不乱码了

校对集

就是按照什么排序而已

常用函数

Floor(向下取整)

Round 四舍五入

Rand() 0到1的随机值

Ceiling 向上取整

Count 非null的个数

Cancat(s1,s2) ...连起来

Length 返回字符串str中的字符数

Trim 去掉头尾空格

索引

是数据的目录,能快速定位行数据的位置

提高查询速度,但是降低了增删改的速度,所以使用索引时,要综合考虑.

一般在查询频率高的列上加,而且在重复列上加效果更好

索引不是越多越好,一般我们在常出现于条件表达式中的列加索引.

值越分散的列,索引的效果越好

索引类型

primary key主键索引

Key 普通索引

unique key'唯一性索引

Email已经重复了,就不让你加

索引长度:建索引时,只取前n个字符当做索引

多列索引 :就是把2列或多列的值的当成一个索引

冗余索引 : 就是在某个列上,可能存在多个索引

比如xm(xing,ming) ming(ming)

索引操作:

查看:show index from t1 或者creat table t1

删除:alter table t1 或者drop index m;

修改 alter table t1 add index/unique 索引名(列名)

事务:

必须选择innodb---支持事务

①开启事务 start transaction

②运行sql;

③提交,同时生效\回滚 commit\rollback

综合练习:

连接上数据库服务器

创建一个gbk编码的数据库

建立商品表和栏目表,字段如下:

商品表:goods

goods_id --主键,

goods_name -- 商品名称

cat_id -- 栏目id

brand_id -- 品牌id

goods_sn -- 货号

goods_number -- 库存量

shop_price -- 价格

goods_desc --商品详细描述

栏目表:category

cat_id --主键

cat_name -- 栏目名称

parent_id -- 栏目的父id

建表完成后,作以下操作:

删除goods表的goods_desc 字段,及货号字段

并增加字段:click_count -- 点击量

在goods_name列上加唯一性索引

在shop_price列上加普通索引

在clcik_count列上加普通索引

删除click_count列上的索引

对goods表插入以下数据:

+----------+------------------------------+--------+----------+-----------+--------------+------------+-------------+

| goods_id | goods_name | cat_id | brand_id | goods_sn | goods_number | shop_price | click_count |

+----------+------------------------------+--------+----------+-----------+--------------+------------+-------------+

| 1 | KD876 | 4 | 8 | ECS000000 | 10 | 1388.00 | 7 |

| 4 | 诺基亚N85原装充电器 | 8 | 1 | ECS000004 | 17 | 58.00 | 0 |

| 3 | 诺基亚原装5800耳机 | 8 | 1 | ECS000002 | 24 | 68.00 | 3 |

| 5 | 索爱原装M2卡读卡器 | 11 | 7 | ECS000005 | 8 | 20.00 | 3 |

| 6 | 胜创KINGMAX内存卡 | 11 | 0 | ECS000006 | 15 | 42.00 | 0 |

| 7 | 诺基亚N85原装立体声耳机HS-82 | 8 | 1 | ECS000007 | 20 | 100.00 | 0 |

| 8 | 飞利浦9@9v | 3 | 4 | ECS000008 | 17 | 399.00 | 9 |

| 9 | 诺基亚E66 | 3 | 1 | ECS000009 | 13 | 2298.00 | 20 |

| 10 | 索爱C702c | 3 | 7 | ECS000010 | 7 | 1328.00 | 11 |

| 11 | 索爱C702c | 3 | 7 | ECS000011 | 1 | 1300.00 | 0 |

| 12 | 摩托罗拉A810 | 3 | 2 | ECS000012 | 8 | 983.00 | 14 |

| 13 | 诺基亚5320 XpressMusic | 3 | 1 | ECS000013 | 8 | 1311.00 | 13 |

| 14 | 诺基亚5800XM | 4 | 1 | ECS000014 | 4 | 2625.00 | 6 |

| 15 | 摩托罗拉A810 | 3 | 2 | ECS000015 | 3 | 788.00 | 8 |

| 16 | 恒基伟业G101 | 2 | 11 | ECS000016 | 0 | 823.33 | 3 |

| 17 | 夏新N7 | 3 | 5 | ECS000017 | 1 | 2300.00 | 2 |

| 18 | 夏新T5 | 4 | 5 | ECS000018 | 1 | 2878.00 | 0 |

| 19 | 三星SGH-F258 | 3 | 6 | ECS000019 | 0 | 858.00 | 7 |

| 20 | 三星BC01 | 3 | 6 | ECS000020 | 13 | 280.00 | 14 |

| 21 | 金立 A30 | 3 | 10 | ECS000021 | 40 | 2000.00 | 4 |

| 22 | 多普达Touch HD | 3 | 3 | ECS000022 | 0 | 5999.00 | 15 |

| 23 | 诺基亚N96 | 5 | 1 | ECS000023 | 8 | 3700.00 | 17 |

| 24 | P806 | 3 | 9 | ECS000024 | 148 | 2000.00 | 36 |

| 25 | 小灵通/固话50元充值卡 | 13 | 0 | ECS000025 | 2 | 48.00 | 0 |

| 26 | 小灵通/固话20元充值卡 | 13 | 0 | ECS000026 | 2 | 19.00 | 0 |

| 27 | 联通100元充值卡 | 15 | 0 | ECS000027 | 2 | 95.00 | 0 |

| 28 | 联通50元充值卡 | 15 | 0 | ECS000028 | 0 | 45.00 | 0 |

| 29 | 移动100元充值卡 | 14 | 0 | ECS000029 | 0 | 90.00 | 0 |

| 30 | 移动20元充值卡 | 14 | 0 | ECS000030 | 9 | 18.00 | 1 |

| 31 | 摩托罗拉E8 | 3 | 2 | ECS000031 | 1 | 1337.00 | 5 |

| 32 | 诺基亚N85 | 3 | 1 | ECS000032 | 1 | 3010.00 | 9 |

+----------+------------------------------+--------+----------+-----------+--------------+------------+-------------+

三 查询知识

注:以下查询基于ecshop网站的商品表(ecs_goods)

在练习时可以只取部分列,方便查看.

1: 基础查询 where的练习:

查出满足以下条件的商品

1.1:主键为32的商品

select goods_id,goods_name,shop_price

from ecs_goods

where goods_id=32;

1.2:不属第3栏目的所有商品

select goods_id,cat_id,goods_name,shop_price from ecs_goods

where cat_id!=3;

1.3:本店价格高于3000元的商品

select goods_id,cat_id,goods_name,shop_price from ecs_goods

where shop_price >3000;

1.4:本店价格低于或等于100元的商品

select goods_id,cat_id,goods_name,shop_price from ecs_goods where shop_price <=100;

1.5:取出第4栏目或第11栏目的商品(不许用or)

select goods_id,cat_id,goods_name,shop_price from ecs_goods

where cat_id in (4,11);

1.6:取出100<=价格<=500的商品(不许用and)

select goods_id,cat_id,goods_name,shop_price from ecs_goods

where shop_price between 100 and 500;

1.7:取出不属于第3栏目且不属于第11栏目的商品(and,或not in分别实现)

select goods_id,cat_id,goods_name,shop_price from ecs_goods where cat_id!=3 and cat_id!=11;

select goods_id,cat_id,goods_name,shop_price from ecs_goods where cat_id not in (3,11);

1.8:取出价格大于100且小于300,或者大于4000且小于5000的商品()

select goods_id,cat_id,goods_name,shop_price from ecs_goods where shop_price>100 and shop_price <300 or shop_price >4000 and shop_price <5000;

1.9:取出第3个栏目下面价格<1000或>3000,并且点击量>5的系列商品

select goods_id,cat_id,goods_name,shop_price,click_count from ecs_goods where

cat_id=3 and (shop_price <1000 or shop_price>3000) and click_count>5;

1.10:取出第1个栏目下面的商品(注意:1栏目下面没商品,但其子栏目下有)

select goods_id,cat_id,goods_name,shop_price,click_count from ecs_goods

where cat_id in (2,3,4,5);

1.11:取出名字以"诺基亚"开头的商品

select goods_id,cat_id,goods_name,shop_price from ecs_goods where goods_name like '诺基亚%';

1.12:取出名字为"诺基亚Nxx"的手机

select goods_id,cat_id,goods_name,shop_price from ecs_goods

where goods_name like '诺基亚N__';

1.13:取出名字不以"诺基亚"开头的商品

select goods_id,cat_id,goods_name,shop_price from ecs_goos

where goods_name not like '诺基亚%';

1.14:取出第3个栏目下面价格在1000到3000之间,并且点击量>5 "诺基亚"开头的系列商品

select goods_id,cat_id,goods_name,shop_price from ecs_goods where

cat_id=3 and shop_price>1000 and shop_price <3000 and click_count>5 and goods_name like '诺基亚%';

select goods_id,cat_id,goods_name,shop_price from ecs_goods where

shop_price between 1000 and 3000 and cat_id=3 and click_count>5 and goods_name like '诺基亚%';

1.15 一道面试题

有如下表和数组

把num值处于[20,29]之间,改为20

num值处于[30,39]之间的,改为30

mian表

+------+

| num |

+------+

| 3 |

| 12 |

| 15 |

| 25 |

| 23 |

| 29 |

| 34 |

| 37 |

| 32 |

| 45 |

| 48 |

| 52 |

+------+

1.16 练习题:

把good表中商品名为'诺基亚xxxx'的商品,改为'HTCxxxx',

提示:大胆的把列看成变量,参与运算,甚至调用函数来处理 .

substring(),concat()

2 分组查询group:

2.1:查出最贵的商品的价格

select max(shop_price) from ecs_goods;

2.2:查出最大(最新)的商品编号

select max(goods_id) from ecs_goods;

2.3:查出最便宜的商品的价格

select min(shop_price) from ecs_goods;

2.4:查出最旧(最小)的商品编号

select min(goods_id) from ecs_goods;

2.5:查询该店所有商品的库存总量

select sum(goods_number) from ecs_goods;

2.6:查询所有商品的平均价

select avg(shop_price) from ecs_goods;

2.7:查询该店一共有多少种商品

select count(*) from ecs_goods;

2.8:查询每个栏目下面

最贵商品价格

最低商品价格

商品平均价格

商品库存量

商品种类

提示:(5个聚合函数,sum,avg,max,min,count与group综合运用)

select cat_id,max(shop_price) from ecs_goods group by cat_id;

3 having与group综合运用查询:

3.1:查询该店的商品比市场价所节省的价格

select goods_id,goods_name,market_price-shop_price as j

from ecs_goods ;

3.2:查询每个商品所积压的货款(提示:库存*单价)

select goods_id,goods_name,goods_number*shop_price from ecs_goods

3.3:查询该店积压的总货款

select sum(goods_number*shop_price) from ecs_goods;

3.4:查询该店每个栏目下面积压的货款.

select cat_id,sum(goods_number*shop_price) as k from ecs_goods group by cat_id;

3.5:查询比市场价省钱200元以上的商品及该商品所省的钱(where和having分别实现)

select goods_id,goods_name,market_price-shop_price as k from ecs_goods

where market_price-shop_price >200;

select goods_id,goods_name,market_price-shop_price as k from ecs_goods

having k >200;

3.6:查询积压货款超过2W元的栏目,以及该栏目积压的货款

select cat_id,sum(goods_number*shop_price) as k from ecs_goods group by cat_id

having k>20000

3.7:where-having-group综合练习题

有如下表及数据

+------+---------+-------+

| name | subject | score |

+------+---------+-------+

| 张三 | 数学 | 90 |

| 张三 | 语文 | 50 |

| 张三 | 地理 | 40 |

| 李四 | 语文 | 55 |

| 李四 | 政治 | 45 |

| 王五 | 政治 | 30 |

+------+---------+-------+

要求:查询出2门及2门以上不及格者的平均成绩

## 一种错误做法

mysql> select name,count(score<60) as k,avg(score) from stu group by name having k>=2;

+------+---+------------+

| name | k | avg(score) |

+------+---+------------+

| 张三 | 3 | 60.0000 |

| 李四 | 2 | 50.0000 |

+------+---+------------+

2 rows in set (0.00 sec)

mysql> select name,count(score<60) as k,avg(score) from stu group by name;

+------+---+------------+

| name | k | avg(score) |

+------+---+------------+

| 张三 | 3 | 60.0000 |

| 李四 | 2 | 50.0000 |

| 王五 | 1 | 30.0000 |

+------+---+------------+

3 rows in set (0.00 sec)

mysql> select name,count(score<60) as k,avg(score) from stu group by name having k>=2;

+------+---+------------+

| name | k | avg(score) |

+------+---+------------+

| 张三 | 3 | 60.0000 |

| 李四 | 2 | 50.0000 |

+------+---+------------+

2 rows in set (0.00 sec)

#加上赵六后错误暴露

mysql> insert into stu

-> values

-> ('赵六','A',100),

-> ('赵六','B',99),

-> ('赵六','C',98);

Query OK, 3 rows affected (0.05 sec)

Records: 3 Duplicates: 0 Warnings: 0

#错误显现

mysql> select name,count(score<60) as k,avg(score) from stu group by name having k>=2;

+------+---+------------+

| name | k | avg(score) |

+------+---+------------+

| 张三 | 3 | 60.0000 |

| 李四 | 2 | 50.0000 |

| 赵六 | 3 | 99.0000 |

+------+---+------------+

3 rows in set (0.00 sec)

#正确思路,先查看每个人的平均成绩

mysql> select name,avg(score) from stu group by name;

+------+------------+

| name | avg(score) |

+------+------------+

| 张三 | 60.0000 |

| 李四 | 50.0000 |

| 王五 | 30.0000 |

| 赵六 | 99.0000 |

+------+------------+

4 rows in set (0.00 sec)

mysql> # 看每个人挂科情况

mysql> select name,score < 60 from stu;

+------+------------+

| name | score < 60 |

+------+------------+

| 张三 | 0 |

| 张三 | 1 |

| 张三 | 1 |

| 李四 | 1 |

| 李四 | 1 |

| 王五 | 1 |

| 赵六 | 0 |

| 赵六 | 0 |

| 赵六 | 0 |

+------+------------+

9 rows in set (0.00 sec)

mysql> #计算每个人的挂科科目

mysql> select name,sum(score < 60) from stu group by name;

+------+-----------------+

| name | sum(score < 60) |

+------+-----------------+

| 张三 | 2 |

| 李四 | 2 |

| 王五 | 1 |

| 赵六 | 0 |

+------+-----------------+

4 rows in set (0.00 sec)

#同时计算每人的平均分

mysql> select name,sum(score < 60),avg(score) as pj from stu group by name;

+------+-----------------+---------+

| name | sum(score < 60) | pj |

+------+-----------------+---------+

| 张三 | 2 | 60.0000 |

| 李四 | 2 | 50.0000 |

| 王五 | 1 | 30.0000 |

| 赵六 | 0 | 99.0000 |

+------+-----------------+---------+

4 rows in set (0.00 sec)

#利用having筛选挂科2门以上的.

mysql> select name,sum(score < 60) as gk ,avg(score) as pj from stu group by name having gk >=2;

+------+------+---------+

| name | gk | pj |

+------+------+---------+

| 张三 | 2 | 60.0000 |

| 李四 | 2 | 50.0000 |

+------+------+---------+

2 rows in set (0.00 sec)

4: order by 与 limit查询

4.1:按价格由高到低排序

select goods_id,goods_name,shop_price from ecs_goods order by shop_price desc;

4.2:按发布时间由早到晚排序

select goods_id,goods_name,add_time from ecs_goods order by add_time;

4.3:接栏目由低到高排序,栏目内部按价格由高到低排序

select goods_id,cat_id,goods_name,shop_price from ecs_goods

order by cat_id ,shop_price desc;

4.4:取出价格最高的前三名商品

select goods_id,goods_name,shop_price from ecs_goods order by shop_price desc limit 3;

4.5:取出点击量前三名到前5名的商品

select goods_id,goods_name,click_count from ecs_goods order by click_count desc limit 2,3;

5 连接查询

5.1:取出所有商品的商品名,栏目名,价格

select goods_name,cat_name,shop_price from

ecs_goods left join ecs_category

on ecs_goods.cat_id=ecs_category.cat_id;

5.2:取出第4个栏目下的商品的商品名,栏目名,价格

select goods_name,cat_name,shop_price from

ecs_goods left join ecs_category

on ecs_goods.cat_id=ecs_category.cat_id

where ecs_goods.cat_id = 4;

5.3:取出第4个栏目下的商品的商品名,栏目名,与品牌名

select goods_name,cat_name,brand_name from

ecs_goods left join ecs_category

on ecs_goods.cat_id=ecs_category.cat_id

left join ecs_brand

on ecs_goods.brand_id=ecs_brand.brand_id

where ecs_goods.cat_id = 4;

5.4: 用友面试题

根据给出的表结构按要求写出SQL语句。

Match 赛程表

字段名称 字段类型 描述

matchID int 主键

hostTeamID int 主队的ID

guestTeamID int 客队的ID

matchResult varchar(20) 比赛结果,如(2:0)

matchTime date 比赛开始时间

Team 参赛队伍表

字段名称 字段类型 描述

teamID int 主键

teamName varchar(20) 队伍名称

Match的hostTeamID与guestTeamID都与Team中的teamID关联

查出 2006-6-1 到2006-7-1之间举行的所有比赛,并且用以下形式列出:

拜仁 2:0 不来梅 2006-6-21

mysql> select * from m;

+-----+------+------+------+------------+

| mid | hid | gid | mres | matime |

+-----+------+------+------+------------+

| 1 | 1 | 2 | 2:0 | 2006-05-21 |

| 2 | 2 | 3 | 1:2 | 2006-06-21 |

| 3 | 3 | 1 | 2:5 | 2006-06-25 |

| 4 | 2 | 1 | 3:2 | 2006-07-21 |

+-----+------+------+------+------------+

4 rows in set (0.00 sec)

mysql> select * from t;

+------+----------+

| tid | tname |

+------+----------+

| 1 | 国安 |

| 2 | 申花 |

| 3 | 公益联队 |

+------+----------+

3 rows in set (0.00 sec)

mysql> select hid,t1.tname as hname ,mres,gid,t2.tname as gname,matime

-> from

-> m left join t as t1

-> on m.hid = t1.tid

-> left join t as t2

-> on m.gid = t2.tid;

+------+----------+------+------+----------+------------+

| hid | hname | mres | gid | gname | matime |

+------+----------+------+------+----------+------------+

| 1 | 国安 | 2:0 | 2 | 申花 | 2006-05-21 |

| 2 | 申花 | 1:2 | 3 | 公益联队 | 2006-06-21 |

| 3 | 公益联队 | 2:5 | 1 | 国安 | 2006-06-25 |

| 2 | 申花 | 3:2 | 1 | 国安 | 2006-07-21 |

+------+----------+------+------+----------+------------+

4 rows in set (0.00 sec)

6 union查询

6.1:把ecs_comment,ecs_feedback两个表中的数据,各取出4列,并把结果集union成一个结果集.

6.2:3期学员碰到的一道面试题

A表:

+------+------+

| id | num |

+------+------+

| a | 5 |

| b | 10 |

| c | 15 |

| d | 10 |

+------+------+

B表:

+------+------+

| id | num |

+------+------+

| b | 5 |

| c | 15 |

| d | 20 |

| e | 99 |

+------+------+

要求查询出以下效果:

+------+----------+

| id | num |

+------+----------+

| a | 5 |

| b | 15 |

| c | 30 |

| d | 30 |

| e | 99 |

+------+----------+

create table a (

id char(1),

num int

)engine myisam charset utf8;

insert into a values ('a',5),('b',10),('c',15),('d',10);

create table b (

id char(1),

num int

)engine myisam charset utf8;

insert into b values ('b',5),('c',15),('d',20),('e',99);

mysql> # 合并 ,注意all的作用

mysql> select * from ta

-> union all

-> select * from tb;

+------+------+

| id | num |

+------+------+

| a | 5 |

| b | 10 |

| c | 15 |

| d | 10 |

| b | 5 |

| c | 15 |

| d | 20 |

| e | 99 |

+------+------+

参考答案:

mysql> # sum,group求和

mysql> select id,sum(num) from (select * from ta union all select * from tb) as tmp group by id;

+------+----------+

| id | sum(num) |

+------+----------+

| a | 5 |

| b | 15 |

| c | 30 |

| d | 30 |

| e | 99 |

+------+----------+

5 rows in set (0.00 sec)

7: 子查询:

7.1:查询出最新一行商品(以商品编号最大为最新,用子查询实现)

select goods_id,goods_name from

ecs_goods where goods_id =(select max(goods_id) from ecs_goods);

7.2:查询出编号为19的商品的栏目名称(用左连接查询和子查询分别)

7.3:用where型子查询把ecs_goods表中的每个栏目下面最新的商品取出来

select goods_id,goods_name,cat_id from ecs_goods where goods_id in (select max(goods_id) from ecs_goods group by cat_id);

7.4:用from型子查询把ecs_goods表中的每个栏目下面最新的商品取出来

select * from (select goods_id,cat_id,goods_name from ecs_goods order by goods_id desc) as t group by cat_id;

7.5 用exists型子查询,查出所有有商品的栏目

select * from category

where exists (select * from goods where goods.cat_id=category.cat_id);

创建触发器:

CREATE trigger tg2

after insert on ord

for each row

update goods set goods_number=goods_number-new.num where id=new.gid

CREATE trigger tg3

after delete on ord

for each row

update goods set goods_number=good_number+old.num where id=old.gid

CREATE trigger tg4

after update on ord

for each row

update goods set goods_number=goods_number+old.num-new.num where id=old.gid


你可能感兴趣的:(数据库,java,人工智能)