MySQL基础教程(第二版)学习笔记

 -- ---------------------unit1----------------------

show databases;

use shop;

show tables;

-- create table

create table Product(

product_id char(4) not null,

product_name varchar(100) not null,

product_type varchar(32) not null,

sale_price integer,

purchase_price integer,

regist_date date,

primary key (product_id)

);

show columns from product;

alter table Product add column on_sale varchar(1) not null;

alter table Product drop column on_sale;

-- DML:insert data

start transaction;

insert into product values ('0001', 'T-Shirt', 'Clothes', 1000, 500, '2023-10-26');

INSERT INTO Product VALUES ('0002', '打孔器', '办公用品', 500, 320, '2009-09-11');

INSERT INTO Product VALUES ('0003', '运动T恤', '衣服', 4000, 2800, null);

INSERT INTO Product VALUES ('0004', '菜刀', '厨房用具', 3000, 2800, '2009-09-20');

INSERT INTO Product VALUES ('0005', '高压锅', '厨房用具', 6800, 5000, '2009-01-15');

INSERT INTO Product VALUES ('0006', '叉子', '厨房用具', 500, NULL, '2009-09-20');

INSERT INTO Product VALUES ('0007', '擦菜板', '厨房用具', 880, 790, '2008-04-28');

INSERT INTO Product VALUES ('0008', '圆珠笔', '办公用品', 100, NULL,'2009-11-11');

commit;

-- alter table's name

rename table product_1 to Product;

-- ------------------------unit2---------------------------

-- 2.1

-- 输出

select product_id, product_name, purchase_price from product;

-- query for all columns

select * from product;

-- use 'AS' to create another name for column

select product_id as id,

product_name as name,

purchase_price as price

from Product;

select product_id as "商品编号",

product_name as "商品名称",

purchase_price as "进货单价"

from Product;

select "商品" as string,

39 as number,

'2023-03-27' as date,

product_id,

product_name

from product;

-- 使用DISTINCT突出明显元素

select distinct product_type from product;

select distinct regist_date from product; -- null也能合并

select distinct product_type, regist_date from product;

-- where语句:查询特定条件

select * from product where product_type = "衣服"

-- 注释

-- 单行注释

/* 多行

注释 */

-- 2.2 算术运算符 和 比较运算符

select product_name as name,

sale_price as price,

sale_price * 2 as "double price"

from product;

select product_name, sale_price as price from product

where purchase_price >= 500;

select product_name, sale_price - purchase_price as margin from product

where sale_price - purchase_price > 500;

-- 2.2 字符串的大小比较

create table chars(chr char(3) not null, primary key(chr));

start transaction;

insert into chars values('1');

insert into chars values('2');

insert into chars values('3');

insert into chars values('10');

insert into chars values('11');

insert into chars values('222');

commit;

select chr from chars where chr > '2'; -- answer is '222' '3'.

-- is null, is not null: 取出/不要null的记录

select product_name, purchase_price

from product

where purchase_price is null;

select product_name, purchase_price

from product

where purchase_price is not null;

-- 2.3逻辑运算符

-- not: 取非

select product_name, product_type, sale_price from product

where not sale_price >= 1000;

-- 用and和or进行多条件查询

select product_name from product

where sale_price >= 1000 and purchase_price >= 500;

-- 括号改变优先级

select product_name from product

where product_type = "办公用品"

and (regist_date = "2009-09-11" or regist_date = "2009-09-20");

-- ----------------- unit3 --------------------

-- --3.1 对表进行聚合查询

-- count/sum/avg/max/min

select count(*) from product; -- 8

select count(purchase_price) from product; -- 6

select sum(sale_price) from product;

select sum(sale_price), sum(purchase_price) from product;

select avg(sale_price) from product;

select max(purchase_price), min(purchase_price) from product;

/* 暂时无法将null也纳入计算范围,具体方法详见 unit6 */

-- 用 聚合函数distinct 删除重复值

select count(distinct product_type) from product;

select sum(sale_price), sum(distinct sale_price) from product;

-- --3.2 对表进行分组(使用group by分组)

select product_type, count(*)

from product

where product_type = '厨房用具' or product_type = '办公用品'

group by product_type;

/* 注意:①使用group by的时候,select的列名可少不可多(聚合键除外)

②group by中不能使用别名(如把‘product_type’简写成‘pro’)(2023.11:MySQL经测试可以使用别名

③where中不能使用聚合函数(count、sum、avg、max、min。。。只有select, having, order by可以)

*/

-- --3.3 为聚合结果指定条件(having)

select product_type, count(*)

from product

group by product_type

having count(*) >= 2;

select product_type, avg(sale_price) as avgsp

from product

group by product_type

having avgsp >= 2500;

-- --3.4 排序(order by)

select product_id, product_name, sale_price, purchase_price

from product

order by sale_price;

select product_id, product_name, sale_price, purchase_price

from product

order by sale_price desc;

-- 两个以上的,更详细的排序

select product_id, product_name, sale_price, purchase_price

from product

order by sale_price, product_id ;

-- null默认排前面

select product_id, product_name, sale_price, purchase_price

from product

order by purchase_price;

-- order by 允许使用别名

select product_id as pid,

product_name as pn,

sale_price as sp,

purchase_price as pp

from product

order by pp desc;

-- ----------------- unit4 插入、删除、更新 --------------------

-- 4.1 数据的插入 insert

-- 创建表

create table productins

(

product_id char(4) not null,

product_name varchar(100) not null,

product_type varchar(32) not null,

sale_price integer default 0,

purchase_price integer ,

regist_date date ,

primary key (product_id)

);

-- 从其他表中复制数据

CREATE TABLE ProductCopy

(product_id CHAR(4) NOT NULL,

product_name VARCHAR(100) NOT NULL,

product_type VARCHAR(32) NOT NULL,

sale_price INTEGER ,

purchase_price INTEGER ,

regist_date DATE ,

PRIMARY KEY (product_id));

insert into productcopy

select * from product;

-- insert ... select 也可以使用 where / grope by等语句

create table producttype(

product_type varchar(32) not null,

sum_sale_price integer ,

sum_purchase_price integer ,

primary key (product_type)

);

insert into producttype

select product_type, sum(sale_price), sum(purchase_price)

from product

group by product_type;

select * from producttype;

-- 4.2 数据的删除 delete

-- 清空

delete from productcopy;

-- 删除部分行

delete from productcopy

where sale_price >= 4000;

-- 4.3 数据的更新 update

-- 更改整列数据

update productcopy

set regist_date = '2009-10-10';

-- 指定条件

update productcopy

set sale_price = sale_price * 10

where product_type = '厨房用具';

-- 将有值的记录更新为null (null清空)

update productcopy

set regist_date = null

where product_id = '0008';

-- 同时对多列进行update(法1)

update productcopy

set sale_price = sale_price * 10,

purchase_price = purchase_price / 2

where product_type = '厨房用具';

-- 同时对多列进行update(法2, mysql不能使用,postgreSQL 和 DB2 可以使用)

update productcopy

set (sale_price, purchase_price) = (sale_price * 10, purchase_price / 2)

where product_type = '厨房用具';

-- 把之前的英文名称T-shirt记录改为中文

update product

set product_name = 'T恤衫',

product_type = '衣服',

regist_date = '2009-09-20'

where product_id = '0001';

-- 4.4事务

/* 现在,请大家把自己想象为管理 Product(商品)表的程序员或者

软件工程师。销售部门的领导对你提出了如下要求。

“某某,经会议讨论,我们决定把运动 T 恤的销售单价下调 1000 日元,

同时把 T 恤衫的销售单价上浮 1000 日元,麻烦你去更新一下数据库。” */

start transaction;

update product

set sale_price = sale_price - 1000

where product_name = "运动T恤";

update product

set sale_price = sale_price + 1000

where product_name = "T恤衫";

commit;

-- 事务回滚 rollback

start transaction;

update product

set sale_price = sale_price - 1000

where product_name = '运动T恤';

update product

set sale_price = sale_price + 1000

where product_name = 'T恤衫';

rollback;

/*

实际上,几乎所有的数据库产品的事务都无需开始指令,像这样不使用指令而悄悄开始事务

的情况下,应该如何区分各个事务呢?通常会有如下两种情况:

A 每条SQL语句就是一个事务(自动提交模式)

B 直到用户执行COMMIT或者ROLLBACK为止算作一个事务

默认使用自动提交模式的DBMS 有 SQL Server、PostgreSQL 和 MySQL 等。

在默认使用 B 模式的 Oracle 中,事务都是直到用户自己执行提交或者回滚指令才会结束。

*/

-- ----------------- unit5 复杂查询--------------------

-- 5.1 视图

-- 创建视图

create view productsum (product_type, cnt_product)

as

select product_type, count(*)

from product

group by product_type ;

-- 使用视图

select product_type, cnt_product

from productsum;

-- 视图上的视图(多重视图)

create view productsumjim(product_type, cnt_product)

as

select product_type, cnt_product

from productsum

where product_type = '办公用品';

/*

虽然语法上没有错误,但是我们还是应该尽量避免在视图的基础上创建视图。

对多数 DBMS 来说,多重视图会降低 SQL 的性能。因此,希望大家(特别是

刚刚接触视图的读者)能够使用单一视图。

*/

-- 另外,1.视图虽然能使用任何select语句,但唯独不能使用order by。

-- 2.经过聚合得到的视图基本无法更新

-- 非聚合视图的更新 !注意!更新视图后,原表也会进行更新。

create view productjim

as

select *

from product

where product_type = '办公用品';

insert into productjim

values ('0009', '印章', '办公用品', 95, 10, '2009-11-30');

-- 删除视图 drop view (若删除一级视图,则二级视图也会失效)

drop view productsum;

-- 复原原表

delete from product

where product_id = '0009';

-- 5.2 子查询

-- 子查询 就是 一次性视图(select语句)

-- 正常创建视图,并进行查询(这不叫子查询)

create view productsum(product_type, cnt_product)

as

select product_type, count(*)

from product

group by product_type;

select * from productsum;

-- 或者使用 子查询:

select *

from (select product_type, count(*) as cnt_product

from product

group by product_type)

as productsum_2; -- 此 select创建的视图 用完就消失,不会保存,属于子查询。

-- 子查询多层嵌套(不建议)

select *

from (select *

from (select product_type, count(*) as cnt_product

from product

group by product_type) as productsum_1

where cnt_product = 4) as productsum_2;

-- 标量子查询

/* 只返回一行一列的数据,其返回值适用于 = 或者 <> 这样

需要单一值的比较运算符之中 */

-- 在where子句中使用标量子查询(因为where子句不能使用聚合函数)

select product_name, sale_price

from product

where sale_price > (select avg(sale_price)

from product);

-- 练习:查询 种类内平均售价 高于 所有商品的平均售价 的数据

select product_type, avg(sale_price) as avgsp

from product

group by product_type

having avgsp > (select avg(sale_price) from product);

-- 5.3 关联子查询

-- 场景:查询 高于自己种类平均售价 的商品。

select product_type, product_name, sale_price

from product as P1

where sale_price > (select avg(sale_price) from product as P2

where p1.product_type = p2.product_type

group by product_type);

-- ----------------- unit6 函数、谓词、CASE表达式--------------------

-- 6.1 函数

-- 建表

create table SampleMath

(m numeric (10,3),

n integer,

p integer);

start transaction;

insert into samplemath values (500, 0, null);

INSERT INTO SampleMath(m, n, p) VALUES (-180, 0, NULL);

INSERT INTO SampleMath(m, n, p) VALUES (NULL, NULL, NULL);

INSERT INTO SampleMath(m, n, p) VALUES (NULL, 7, 3);

INSERT INTO SampleMath(m, n, p) VALUES (NULL, 5, 2);

INSERT INTO SampleMath(m, n, p) VALUES (NULL, 4, NULL);

INSERT INTO SampleMath(m, n, p) VALUES (8, NULL, 3);

INSERT INTO SampleMath(m, n, p) VALUES (2.27, 1, NULL);

INSERT INTO SampleMath(m, n, p) VALUES (5.555,2, NULL);

INSERT INTO SampleMath(m, n, p) VALUES (NULL, 1, NULL);

INSERT INTO SampleMath(m, n, p) VALUES (8.76, NULL, NULL);

COMMIT;

select * from samplemath;

create table SampleStr

(str1 varchar(40),

str2 varchar(40),

str3 varchar(40));

start transaction;

insert into samplestr values ('opx','rt',null);

INSERT INTO SampleStr (str1, str2, str3) VALUES ('abc' ,'def' ,NULL);

INSERT INTO SampleStr (str1, str2, str3) VALUES ('山田' ,'太郎' ,'是我');

INSERT INTO SampleStr (str1, str2, str3) VALUES ('aaa' ,NULL ,NULL);

INSERT INTO SampleStr (str1, str2, str3) VALUES (NULL ,'xyz',NULL);

INSERT INTO SampleStr (str1, str2, str3) VALUES ('@!#$%' ,NULL ,NULL);

INSERT INTO SampleStr (str1, str2, str3) VALUES ('ABC' ,NULL ,NULL);

INSERT INTO SampleStr (str1, str2, str3) VALUES ('aBC' ,NULL ,NULL);

INSERT INTO SampleStr (str1, str2, str3) VALUES ('abc太郎' ,'abc' ,'ABC');

INSERT INTO SampleStr (str1, str2, str3) VALUES ('abcdefabc' ,'abc' ,'ABC');

INSERT INTO SampleStr (str1, str2, str3) VALUES ('micmic' ,'i' ,'I');

COMMIT;

select * from samplestr;

-- ------算术函数:------

-- abs绝对值

select m, abs(m) as abs_col from samplemath;

-- mod求余

select n, p,

mod(n, p) as mod_n_p

from samplemath ;

-- round(值,保留几位小数) 四舍五入

select m, round(m,2) as '保留两位小数'

from samplemath;

-- ------字符串函数:------

-- concat(字符串1, 字符串2, ...) 拼接

select str1, str2, concat(str1, str2) as str_concat

from samplestr;

select str1, str2, str3, concat(str1, str2, str3) as str_concat

from samplestr;

-- length(str) 、 char_length(str) 计算字符串长度

select str1, length(str1) as len_str1

from samplestr; -- length里,汉字这样的全角字符会占用 2 个以上的字节

select str1, char_length(str1) as charlen_str1

from samplestr;

-- lower(str) upper(str)

select str1, lower(str1) as low_str

from samplestr;

select str1, upper(str1) as upr_str

from samplestr;

-- replace(对象str,要替换的部分,替换内容) 把一部分字符串换成另一部分

select str1, str2, str3, replace(str1, str2, str3)

from samplestr;

-- substring(对象str from 起始位置 for 截取数量)

select str1, substring(str1 from 3 for 2) as sub_str

from samplestr;

-- where str in ('', '', '', ...)

-- ------日期函数:------

select current_date; -- 获取当前日期

select current_time; -- 获取当前时间

select current_timestamp -- 当前日期+时间

-- extract(元素 from 日期函数) 提取 日期函数内 的元素

select current_timestamp,

extract(year from current_timestamp) as year,

extract(month from current_timestamp) as month,

extract(day from current_timestamp) as day,

extract(hour from current_timestamp) as hour,

extract(minute from current_timestamp) as minute,

extract(second from current_timestamp) as second;

-- ------转换函数:------

-- cast(转换前的值 as 想转换的数据类型) 数据类型转换

select cast('0001' as signed integer) as int_col; -- 有符号整数

select cast('2009-12-14' as date) as date_col;

-- coalesce(数据1,数据2,数据3……) 返回 从左往右 第一个不是null的值

select coalesce(null, 1) as col_1,

COALESCE(NULL, 'test', NULL) AS col_2,

COALESCE(NULL, NULL, '2009-11-01') AS col_3;

select coalesce(str2, 'IS NULL') as coa_str2

from samplestr;

-- 6.2 谓词

-- 建表

create table SampleLike

(strcol varchar(10));

start transaction;

insert into samplelike values ('abcddd');

insert into samplelike values ('dddabc');

insert into samplelike values ('abdddc');

insert into samplelike values ('abcdd');

insert into samplelike values ('ddabc');

insert into samplelike values ('abddc');

commit;

-- like % _ 模糊查询

select strcol

from samplelike

where strcol like 'ddd%';

select strcol

from samplelike

where strcol like '%ddd%';

select strcol

from samplelike

where strcol like '%ddd'; -- % 任意字符

select strcol

from samplelike

where strcol like 'abc__'; -- _ 任意1个字符

-- between 范围查询

select product_name, sale_price

from product

where sale_price between 100 and 1000; -- between特点:包含临界值

-- is null, is not null 判断是否为null

select product_name, purchase_price

from product

where purchase_price is null;

select product_name, purchase_price

from product

where purchase_price is not null;

-- in, not in 把多条or变成一条in or……,or…… --》 in (……,……)

select product_name, purchase_price

from product

where purchase_price in (320, 500, 5000);

select product_name, purchase_price

from product

where purchase_price not in (select max(purchase_price)

from product); -- 标量子查询 运用:去掉最大值

-- in谓词 + 子查询 进行跨表查询 --

CREATE TABLE ShopProduct

(shop_id CHAR(4) NOT NULL,

shop_name VARCHAR(200) NOT NULL,

product_id CHAR(4) NOT NULL,

quantity INTEGER NOT NULL,

PRIMARY KEY (shop_id, product_id));

start TRANSACTION;

INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000A', '东京', '0001', 30);

INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000A', '东京', '0002', 50);

INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000A', '东京', '0003', 15);

INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0002', 30);

INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0003', 120);

INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0004', 20);

INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0006', 10);

INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0007', 40);

INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000C', '大阪', '0003', 20);

INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000C', '大阪', '0004', 50);

INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000C', '大阪', '0006', 90);

INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000C', '大阪', '0007', 70);

INSERT INTO ShopProduct (shop_id, shop_name, product_id, quantity) VALUES ('000D', '福冈', '0001', 100);

COMMIT;

select product_id

from shopproduct

where shop_id = '000C'; -- ①

select product_name, sale_price

from product

where product_id in (select product_id

from shopproduct

where shop_id = '000C' -- ①

);

-- 练习:在product中选取 在东京店(000A)以外销售 的商品

select product_name, sale_price

from product p

where product_id not in (select product_id

from shopproduct

where shop_id = '000A'

);

-- exists exsits(关联子查询)

select product_name, sale_price

from product p

where exists (select * from shopproduct sp

where sp.shop_id = '000C' and sp.product_id = p.product_id

);

-- 对 exists 中, 关联子查询使用 select * 的说明

select 1

from product p ; -- 返回一列 列名和内容都为1 的列

select product_name, sale_price

from product p

where exists (select 1 from shopproduct sp

where sp.shop_id = '000C' and sp.product_id = p.product_id

); -- exists 只关心 where语句中的判断,因此即使 select 1 也不会影响结果

-- 可以把在 exists 的子查询中书写 SELECT * 当作 SQL 的一种习惯

-- 练习:用 not exist 在 product 中选取 在东京店(000A)以外销售 的商品名称、销售价格

select product_name, sale_price

from product p

where not exists (select * from shopproduct sp

where shop_id = '000A' and sp.product_id = p.product_id

);

-- 6.3 case (case表达式也是函数的一种,是SQL中数一数二的重要功能)

-- 搜索case 包含了 简单case的所有功能

-- 用case将 A、B、C 和 不同商品种类字段 合并

select product_name,

case when product_type = '衣服' then concat('A:', product_type)

when product_type = '办公用品' then concat('B:', product_type)

when product_type = '厨房用具' then concat('C:', product_type)

else null -- 含义:上述情况之外时返回 null。

-- ELSE 子句也可以省略不写,这时会被默认为 ELSE NULL。

end as abc_product_type -- end不能省略。

from product p;

-- 用 case 输出一个 行列转换表(相对于group by)

select product_type , sum(sale_price) as sum_price

from product

group by product_type;

/* sum_price_clothes | sum_price_kitchen | sum_price_office

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

5000 | 11180 | 600 */

select sum(case when product_type = '衣服' then sale_price else 0 end) as sum_price_clothes,

sum(case when product_type = '厨房用具' then sale_price else 0 end) as sum_price_kitchen,

sum(case when product_type = '办公用品' then sale_price else 0 end) as sum_price_office

from product p ;

-- ----------------- unit7 集合运算--------------------

CREATE TABLE Product2

(product_id CHAR(4) NOT NULL,

product_name VARCHAR(100) NOT NULL,

product_type VARCHAR(32) NOT NULL,

sale_price INTEGER ,

purchase_price INTEGER ,

regist_date DATE ,

PRIMARY KEY (product_id));

START TRANSACTION;

INSERT INTO Product2 VALUES ('0001', 'T恤衫' ,'衣服', 1000, 500, '2008-09-20');

INSERT INTO Product2 VALUES ('0002', '打孔器', '办公用品', 500, 320, '2009-09-11');

INSERT INTO Product2 VALUES ('0003', '运动T恤', '衣服', 4000, 2800, NULL);

INSERT INTO Product2 VALUES ('0009', '手套', '衣服', 800, 500, NULL);

INSERT INTO Product2 VALUES ('0010', '水壶', '厨房用具', 2000, 1700, '2009-09-20');

COMMIT;

-- 7.1 表的加减法

/* 集合运算注意事项

1. 列数 要相同,数据类型 要相同。

2. order by 只能在最后使用一次,其他select语句 无限制。 */

-- union 表的加法

select product_id, product_name

from product

union

select product_id, product_name

from product2;

select product_id, product_name

from product

union all -- union all 保留重复项

select product_id, product_name

from product2;

-- except 表的减法 注意:减数和被减数的位置不同,所得到的结果也不相同

select product_id, product_name

from product

except

select product_id, product_name

from product2;

-- intersect 表的交集

select product_id, product_name

from product

intersect

select product_id, product_name

from product2;

-- 7.2 联结(以列为单位对表进行联结)

CREATE TABLE InventoryProduct

( inventory_id CHAR(4) NOT NULL,

product_id CHAR(4) NOT NULL,

inventory_quantity INTEGER NOT NULL,

PRIMARY KEY (inventory_id, product_id));

start TRANSACTION;

INSERT INTO InventoryProduct (inventory_id, product_id, inventory_quantity) VALUES ('P001', '0001', 0);

INSERT INTO InventoryProduct (inventory_id, product_id, inventory_quantity) VALUES ('P001', '0002', 120);

INSERT INTO InventoryProduct (inventory_id, product_id, inventory_quantity) VALUES ('P001', '0003', 200);

INSERT INTO InventoryProduct (inventory_id, product_id, inventory_quantity) VALUES ('P001', '0004', 3);

INSERT INTO InventoryProduct (inventory_id, product_id, inventory_quantity) VALUES ('P001', '0005', 0);

INSERT INTO InventoryProduct (inventory_id, product_id, inventory_quantity) VALUES ('P001', '0006', 99);

INSERT INTO InventoryProduct (inventory_id, product_id, inventory_quantity) VALUES ('P001', '0007', 999);

INSERT INTO InventoryProduct (inventory_id, product_id, inventory_quantity) VALUES ('P001', '0008', 200);

INSERT INTO InventoryProduct (inventory_id, product_id, inventory_quantity) VALUES ('P002', '0001', 10);

INSERT INTO InventoryProduct (inventory_id, product_id, inventory_quantity) VALUES ('P002', '0002', 25);

INSERT INTO InventoryProduct (inventory_id, product_id, inventory_quantity) VALUES ('P002', '0003', 34);

INSERT INTO InventoryProduct (inventory_id, product_id, inventory_quantity) VALUES ('P002', '0004', 19);

INSERT INTO InventoryProduct (inventory_id, product_id, inventory_quantity) VALUES ('P002', '0005', 99);

INSERT INTO InventoryProduct (inventory_id, product_id, inventory_quantity) VALUES ('P002', '0006', 0);

INSERT INTO InventoryProduct (inventory_id, product_id, inventory_quantity) VALUES ('P002', '0007', 0);

INSERT INTO InventoryProduct (inventory_id, product_id, inventory_quantity) VALUES ('P002', '0008', 18);

COMMIT;

-- inner join 内联结

select sp.shop_id, sp.shop_name, sp.product_id, p.product_name, p.sale_price

from shopproduct sp inner join product p

on sp.product_id = p.product_id;

/* 要点:1. select 后使用 <表名>.<列名> 形式

2. from 后有两张以上的表

3. on 之后要指定两张表间的 联结键 */

-- 内联结和 where 子句的结合使用 (对 联结后得到的表 进行筛选)

select sp.shop_id, sp.shop_name, sp.product_id, p.product_name, p.sale_price

from shopproduct sp inner join product p

on sp.product_id = p.product_id

where sp.shop_id = '000A';

-- outer join 外联结 (对有外联结的DBMS来说,左右外联结果一样,彼此没有的数据以null表示)

/* 注意! MySQL没有外联结的概念!

取而代之的是左联结、右联结:left join、right join。左右联结结果并不相同!

A left join B : ( A ) B )

A right join B : ( A ( B )

*/

select sp.shop_id, sp.shop_name, sp.product_id, p.product_name, p.sale_price

from shopproduct sp right outer join product p

on sp.product_id = p.product_id; -- 依product表,所以sp表中没有的项目以null表示。

-- 三张表以上的联结

select sp.shop_id, sp.shop_name, sp.product_id,

p.product_name, p.sale_price, ip.inventory_quantity

from shopproduct sp inner join product p

on sp.product_id = p.product_id

inner join inventoryproduct ip

on sp.product_id = ip.product_id

where ip.inventory_id = 'P001'

order by ip.inventory_quantity desc;

-- cross join 交叉联结

/* 交叉联结在实际业务中并不会使用,但是是所有联结运算的基础 */

select SP.shop_id, SP.shop_name, SP.product_id, P.product_name

from ShopProduct SP cross join Product P;

-- 除法集合运算

/* 本章中我们学习了以下 4 个集合运算符。

● UNION(并集)

● EXCEPT(差集)

● INTERSECT(交集)

● CROSS JOIN(笛卡儿积)

难道集合运算中没有除法吗?当然不是,除法运算是存在的。集合运算中的

除法通常称为关系除法。

除法运算是集合运算中最复杂的运算,但是其在实际业务中的应用十分广泛,

因此希望大家能在达到中级以上水平时掌握其使用方法。此外,想要详细了解 SQL

中除法运算实现方法的读者,可以参考拙著《達人に学ぶ SQL 徹底指南書》

( 翔泳社 ) 中的 1-4 节和 1-7 节。 */

-- ----------------- unit8 SQL高级处理--------------------

-- 8.1 窗口函数(OLAP函数 OnLine Analytical Processing 实时分析处理)

-- rank 排序 (1,1,1),4

select product_name, product_type, sale_price,

rank() over (partition by product_type

order by sale_price) as ranking

from product;

-- 去掉partition

select product_name, product_type, sale_price,

rank() over (order by sale_price) as ranking

from product;

-- dense_rank (1,1,1),2

select product_name, product_type, sale_price,

dense_rank() over(order by sale_price) as dranking

from product;

-- row_number (1,2,3),4

select product_name, product_type, sale_price,

row_number() over(order by sale_price) as dranking

from product;

-- practise_1

create table addressbook(

regist_no integer not null,

name varchar(128) not null,

address varchar(256) not null,

tel_no char(10),

mail_address char(20),

primary key (regist_no)

);

alter table addressbook add column postal_code char(8) not null;

drop table addressbook;

-- practise_2

select product_name, regist_date from product

where regist_date > "2009-04-28";

select product_name, product_type,

sale_price * 0.9 - purchase_price as profit

from product

where sale_price * 0.9 - purchase_price > 100;

-- practise_3

-- 3.1 错误点:1.对文本内容使用sum 2.

-- 3.2

select product_type, sum(sale_price), sum(purchase_price)

from product

group by product_type

having sum(sale_price) >= sum(purchase_price) * 1.5;

-- 3.3

select *

from product

order by regist_date desc, sale_price;

-- practise_4

-- 4.1 会得到一个空表,因为没有提交。

CREATE TABLE ProductCopy_2

(product_id CHAR(4) NOT NULL,

product_name VARCHAR(100) NOT NULL,

product_type VARCHAR(32) NOT NULL,

sale_price INTEGER ,

purchase_price INTEGER ,

regist_date DATE ,

PRIMARY KEY (product_id));

start transaction;

INSERT INTO ProductCopy_2 VALUES ('0001', 'T恤衫', '衣服', 1000, 500, '2008-09-20');

INSERT INTO ProductCopy_2 VALUES ('0002', '打孔器', '办公用品', 500, 320, '2008-09-11');

INSERT INTO ProductCopy_2 VALUES ('0003', '运动T恤', '衣服', 4000, 2800, NULL)

select * from ProductCopy_2;

-- 4.2 可以这样做

/*错! 正确答案是不行,违反了主键约束,即主键不能有重复记录*/

-- 4.3

CREATE TABLE ProductMargin

(product_id CHAR(4) NOT NULL,

product_name VARCHAR(100) NOT NULL,

sale_price INTEGER,

purchase_price INTEGER,

margin INTEGER,

PRIMARY KEY(product_id));

insert into productmargin

select product_id,

product_name,

sale_price,

purchase_price,

sale_price - purchase_price as margin

from product

limit 3;

-- 4.4

/*

‘sale_price - purchase_price as margin’ 不会随着

sale_price 和 purchase_price的变化而变化,必须手动更改。

*/

update productmargin

set sale_price = sale_price - 1000,

margin = sale_price - purchase_price

where product_id = '0003';

-- practice_5

-- 5.1

create view ViewPractice5_1

as

select product_name, sale_price, regist_date

from product

where sale_price >= 1000 and regist_date = '2009-09-20';

select * from viewpractice5_1;

drop view viewpractice5_1;

-- 5.2

insert into viewpractice5_1 values('刀子',300, '2009-11-02');

-- 答:往视图中插入不符合条件的记录,会出错

-- 5.3

select product_id,

product_name,

product_type,

sale_price,

(select avg(sale_price) from product) as sale_price_all

from product;

-- 5.4 关联子查询 练习

create view AvgPriceByType

as

select product_id, product_name, product_type, sale_price,

(select avg(sale_price)

from product as p2

where p1.product_type = p2.product_type

group by product_type) as avg_sale_price

from product as p1;

-- practice_6

-- 6.1

/*

对本章中使用的 Product(商品)表执行如下 2 条 SELECT 语句,能够得

到什么样的结果呢? */

-- ①

SELECT product_name, purchase_price

FROM Product

WHERE purchase_price NOT IN (500, 2800, 5000);

-- ②

SELECT product_name, purchase_price

FROM Product

WHERE purchase_price NOT IN (500, 2800, 5000, NULL);

/* 答:①320,790

②选不出任何记录。这个是SQL的危险陷阱,属于中级学习范畴,

在平常使用in,not in时,参数里不要加入null。 */

-- 如何避免这一陷阱,或者选出null记录? 使用coalesce 把 空值null 变成 字符串null 。

SELECT product_name, purchase_price

FROM Product

WHERE coalesce(purchase_price, 'NULL') not IN (500, 2800, 5000, 'NULL');

SELECT product_name, purchase_price

FROM Product

WHERE coalesce(purchase_price, 'NULL') IN (500, 2800, 5000, 'NULL');

-- 6.2

/* low_price | mid_price | high_price

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

5 | 1 | 2 */

select count(case when sale_price <= 1000 then 1 else null end) as low_price,

count(case when sale_price > 1000 and sale_price <= 3000 then 1 else null end) as mid_price,

count(case when sale_price > 3000 then 1 else null end) as high_price

from product; -- count原理 : 值不为 null 便计一次数

-- practice_7

-- 7.1 结果不变

-- 7.2

select coalesce(sp.shop_id, '不确定') as shop_id,

coalesce(sp.shop_name, '不确定') as shop_name,

coalesce(sp.product_id, '不确定') as product_id,

p.product_name,

p.sale_price

from shopproduct sp right join product p

on sp.product_id = p.product_id;

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值