目录

第一章:基本关键字学习

1.1 WHERE

1.2 AND OR

1.3  IN

1.4 BETWEEN

1.5  IS NULL

1.6 LIMIT

1.7 ORDER BY

 1.8 LIKE

1.9 REGEXP

 第二章:“表”之间的连接

2.1 内连接(INNER JOIN)

2.2 跨数据库连接

2.3 自连接

2.4 多表连接

2.5 复合连接条件

2.6 外连接

 2.7 隐式连接

2.8 多表外连接

2.9 自外连接

2.10 USING语句

 2.11 自然连接

 2.12 交叉连接

2.13 UNION联合






第一章:基本关键字学习

最基础内容,打开数据库的具体的一张表

USE 数据库名;

SELECT *
-- 这里的*,可以替换成表的表头信息(你需要的内容)
FROM 表名

1.1 WHERE

SELECT *
FROM customers
# 选择出points > 3000的内容
-- >,<,<=,>=,!=
-- WHERE points > 3000

-- state为VA的内容
-- WHERE state = 'VA'

-- state不为VA的内容
-- WHERE state != 'VA'
WHERE birth_date > '1990-01-01'

1.2 AND OR

# 来解释AND,OR,NOT运算符
# 如何在筛选数据时候结合多条搜索条件,
# 比如,获取所有在1990-1-1以后出生的顾客,并且积分点超了1000
SELECT *
FROM customers
-- WHERE birth_date >= '1990-01-01' AND points > 1000
# 逻辑运算符的优先级
# AND OR
WHERE NOT birth_date > '1990-01-01' OR 
		(points > 1000 AND state = 'VA')

1.3  IN

# IN 运算符
# 假设你想获取定位与VA或者Florida或者Georgia的顾客
SELECT *
FROM customers
-- WHERE state = 'VA' OR state = 'GA' OR state = 'FL'
# OR不能直接在后面连接字符串,而IN 的内部是可以直接使用字符串的
# 与OR有一些不同

-- WHERE state IN ('VA','FL')
WHERE state NOT IN ('VA','FL')

1.4 BETWEEN

# BETWEEN运算符
# 假如我们想要获取积分结余1000到3000之间的顾客
SELECT *
FROM customers
-- WHERE points >= 1000 AND points <= 3000
WHERE points BETWEEN 1000 AND 3000

1.5  IS NULL

# IS NULL 运算符
# 如何搜索缺失的内容
# 如果选取了数据库中所有的顾客,id=5没有phonenum
SELECT *
FROM customers
-- WHERE phone IS NULL 
WHERE phone IS NOT NULL

1.6 LIMIT

# LIMIT子句
# 如何限定查询返回的记录
# 比如,我们得到全部的内容,现在只想要前三位的顾客
SELECT *
FROM customers
-- LIMIT 3

# 此外,我们可以选择性添加一个偏移量(offset),
# 这在想要给数据分页的时候很有用
# 比如,只想要一个界面显示三个顾客
-- page1 : 1-3
-- page2 : 4-6
-- page3 : 7-9
-- 现在想要获取第三页的顾客,怎么做?
-- 跳过前6条就好
LIMIT 6, 3   # 6为偏移量

1.7 ORDER BY

# ORDER BY 子句
# 如何使用SQL查询为数据排序·
# 选择CUSTOMERS中间的那个设置按钮,我们可以点击,
# 进入到表的内部
# 我们可以看到有一个黄色的标志,他是这个表的主键列,这一列能够唯一识别表的内容
-- DESC表示降序排列
-- SELECT *
-- FROM customers
-- ORDER BY first_name # 这默认是升序,可以改为降序
-- ORDER BY first_name DESC   # DESC表示降序

# 可以给多列数据排序
# 首先根据州来给顾客排序,然后在每个州李用名字排序
-- ORDER BY state, first_name
-- ORDER BY state DESC, first_namE 

# MYSQL可以用任何列排序数据,不管那列是不是在select子句中
# 虽然我们在选择的时候,只选了first_name, last_name这两列
# 但是在排序的时候,不影响我们使用表中的其他内容

-- SELECT first_name, last_name
-- FROM customers
-- ORDER BY birth_date


SELECT first_name, last_name
FROM customers
ORDER BY 1, 2   # 这里的12就是上面选择的内容,按照上面选择的进行排序。

 1.8 LIKE

# LIKE运算符
# 如何检索遵循特定字符串模型的行
# 假设,我们只想要获取姓氏以‘B’开头的顾客
SELECT *
FROM customers
# 想要获得b开头的姓氏的顾客,b之后可能有任意长度的字符
# 用%表示任意字数的字符
# %b%=======中间有b, %y======结尾是y
# 此外,下划线"_",表示一个单字符
# _y=======表示输入只有两个字符,第一个字符是任意的,第二个必须是y
WHERE last_name LIKE '_____y'

1.9 REGEXP

这里的“正则”和Python的正则化很类似。

# REGEXP运算符
# 假如你想要搜寻顾客,顾客姓氏有‘field’单词
# regexp就是正则,在搜索字符串及其强大

-- ^ 表示开始位置
-- $ 表示末尾
-- | 表示OR的意思
-- [adcf] []内匹配在括号内的列举单个字符
-- [a-h]  表示a到h这个范围

SELECT *
FROM customers
-- WHERE last_name LIKE '%fiel%'
-- WHERE last_name REGEXP 'FIELD'
# 我们可以在字符串前面加"^"这个符号,意思就是必须以XXX打头
# 我们可以在字符串末尾加"$"这个符号,意思就是必须以XXX结尾

-- WHERE last_name REGEXP 'd$'

# 如果想要多个查询的话,用|隔开,|表示多个查询
-- WHERE last_name REGEXP 'fiel|mac'

# e前面有g、i、m字母,如ge,ie,me。[gim]e;e[gim];[a-h]e
WHERE last_name REGEXP '[gim]e'

 第二章:“表”之间的连接

2.1 内连接(INNER JOIN)

第一章的内容描述的是从一张表中提取筛选内容。如何从多张表格中选取内容呢?需要用到join。通常,使用到内连接的时候,INNER可以省略不写。
-- 现实生活中通常需要从多张表格选取列
-- 如果我们查询orders表格
-- 在这个表中,我们需要用customer_id列来识别每笔订单的顾客
-- 在这个表中,没有存储如电话号邮箱等其他信息,因为这个信息可能会变化
-- 如果顾客下了多笔订单的话,我们需要来回改动多条记录
-- 把顾客的订单放在不同的表格

-- select *  # 这是显示全部内容,SQL是不区分大小写的
-- 也可以选择我们需要的字段
select order_id, customer_id, first_name, last_name
from orders
-- 想要选取orders表中的一切,现在要合并这张表的列和customers表的列
-- 使用join关键字
-- 选择内连接,INNER JOIN(inner这个关键字可以打也可以不打)
-- 想要和customers链接
-- 基于什么连接这些表呢?
-- 在customers表中,有customer_id这一列,如果要把两张表连在一起,需要联合记录
-- 使得顾客的id相同,我们可以使用ON关键字
join customers
    on orders.customer_id = customers.customer_id


-- 我们发现,在上面这个代码中,orders和customers出现了很多次,我们可以给表用个别名
SELECT order_id,o.customer_id, c.first_name, c.last_name
FROM orders o
INNER JOIN customers c 
		ON o.customer_id = c.customer_id
        -- 要注意的是,如果你用了别名的话,后面有关的内容全部要改名,不然会报错

2.2 跨数据库连接

-- 跨数据库链接
-- 从事数据库管理的工作,用到多个数据库
-- 如何将分散在多个数据的表中的列合并起来
-- 比如sql_store表中的product这表不在了,查看sql_inventory数据库
-- 这两个product是一样的
-- 但是,不同的数据库有相同的内容,是不合理的
-- 我们想把order_item表和sql_inventory数据的product连接在一起

-- USE sql_inventory;
USE sql_store;

SELECT *
FROM sql_store.order_items oi
JOIN sql_inventory.products p
	ON oi.product_id = p.product_id
-- 这样,我们成功连接了夸数据库的表格
-- 我们发现,sql_store在products前面,
-- 因为当前这个段查询的数据库是sql_store数据库

2.3 自连接

-- sql中,我们可以将一张表和自己连接
-- 我们打开sql_hr的表格employees
-- reports_to 汇报对象--管理者的id
-- 所以只用识别符或者id来表示他们
-- 在哪可以找到这个管理者的信息呢?
-- 我们发现,他也是一名员工,但是,他的report_to的对象没有,可能人家是CEO
-- 写一段查询,把这张表和自己连接一下,
-- 这样就可以选择每个员工和他们管理者的名字

USE sql_hr;

-- SELECT *  
# 我们发现,全选的话,会出现重复的内容
# 前面是员工信息,后面是管理者信息
SELECT 
    e.employee_id,
    e.first_name,
    m.first_name AS m_first_name
FROM employees e
-- 我们需要再次连接这个表作为自连接
-- 但是需要不同的别名,目的是找到管理人员
JOIN employees m
    ON e.reports_to = m.employee_id

2.4 多表连接

-- 怎么连接超过两张表
-- 回到sql_store
-- 看看orders表,其中有state这个列,但是这列的具体内容存在别的表中
-- 写一段查询连接orders表同其他两个表customers和statuses表
-- 结果:order_id,order_date,first,last,status

USE sql_store;

-- SELECT *
SELECT
    o.order_id,
    o.order_date,
    c.first_name,
    c.last_name,
    os.name
FROM orders o
# 接下来,进行联合
JOIN customers c
    ON o.customer_id = c.customer_id
JOIN order_statuses os
    ON o.status = os.order_status_id

 2.5 复合连接条件

-- 用单一列唯一识别某张表的行,
-- 比如在customer表中,有顾客id,唯一识别了这张表的行
-- 但是存在无法用单一列来准确识别某张表里列的情况
-- 比如, order_item,无法用order_id来做唯一标识列,因为里面有重复的
-- 在这张表中,用前两列的值在一起作为唯一识别的内容
-- 标识符就是主键,主键可以是一列或者多列
-- 打开order_item的设计者模式,发现前两列都有黄色标识--复合主键
-- 如何将这张表和别的表进行连接
-- `order_item_notes`记录每个订单的注释
-- 有note_id,他唯一识别这账表的记录

USE sql_store;

SELECT *
FROM order_items oi
JOIN order_item_notes oin
    ON oi.order_id = oin.order_id
    AND oi.product_id = oin.product_id

2.6 外连接

看“2.1 内连接”

-- 2.1的代码我们可以返回10个值,其中customer_id有10,8,7,6,5,2
-- 那是因为的结果集中只包含6位顾客,其他的顾客没有订单
-- 但是顾客表会有别的顾客信息,
-- 现在,我想看所有顾客,不管有没有订单
-- 这是可以用外连接,
-- 外连接有两种形式,一个是左连接(LEFT JOIN),一个是右连接(RIGHT JOIN)
-- 左连接
    -- 所有左表的记录,在本案例中的顾客会被返回
-- left join(左连接)返回包括 左表中的所有记录 和右表中连接字段相等的记录

-- right join(右连接)返回包括 右表中的所有记录 和左表中连接字段相等的记录

SELECT
    c.customer_id,
    c.first_name,
    c.last_name,
    o.order_id
/*    
FROM customers c
# 注意,这里的左右 是和 customers为左和orders为右
LEFT JOIN orders o  # 首先返回的是customers o的全部内容,因为是对他做链接
     ON o.customer_id=c.customer_id
*/

FROM orders o
# 注意,这里的左右 是和 customers为左和orders为右
right JOIN customers c  # 首先返回的是orders o的全部内容,因为是对他做链接
     ON o.customer_id=c.customer_id


ORDER BY c.customer_id

 2.7 隐式连接

-- 隐式连接语法
-- 简单的连接
/*
SELECT *
FROM orders o
JOIN customers c
	ON o.customer_id = c.customer_id
*/
-- 可以用隐式的方法去写
SELECT *
FROM orders o, customers c
-- WHERE o.customer_id = c.customer_id
-- 如果不写where的话,就会得到很多条数据
-- 订单表的每条记录都和顾客标的每条记录进行连接了
-- 也就是交叉连接

2.8 多表外连接

SELECT
	c.customer_id,
    c.first_name,
    o.order_id,
    sh.name AS shipper_name
/*    
FROM customers c
# 注意,这里的左右 是和 customers为左和orders为右
LEFT JOIN orders o  # 首先返回的是orders o的全部内容,因为是对他做链接
 	ON o.customer_id=c.customer_id
*/

FROM customers c
# 注意,这里的左右 是和 customers为左和orders为右
LEFT JOIN orders o  # 首先返回的是customers c的全部内容,因为是对他做链接
 	ON o.customer_id=c.customer_id

-- 将shippers表和customers做内连接
left JOIN shippers sh
	ON o.shipper_id = sh.shipper_id


ORDER BY c.customer_id 

-- 查看order表,发现,有些订单有订单人id和发货人信息
-- 订单表和发货人表进行连接

2.9 自外连接

-- sql的自连接,在sql_hr的一张表
-- 获取员工的管理人员,用的是自连接

use sql_hr;

select 
    e.employee_id,
    e.first_name,
    m.first_name as manger
from employees e
-- join employees m
left join employees m  # 这样就会出现所有的员工,包括那个ceo
    on e.reports_to = m.employee_id
-- 上面那个就是自内连接

2.10 USING语句

use sql_store;

select 
    o.order_id,
   sh.name as shipper,
   c.first_name
from orders o
join customers c
    on o.customer_id = c.customer_id  
-- 以上是一个简单的查询,连接了订单表和顾客表
-- 比如上面的句子,我们发现o.customer_id = c.customer_id
-- 有两个列名是相同的,我们可以用using子句来替换on

    using (customer_id)
left join shippers sh
    using (shipper_id)

-- using关键字只能在不同表的列名相同的情况下使用
-- 在连接条件中添加多列怎么办?
-- 比如,order_item中有个复合主键,一个主键包含了多列
-- 现在想要链接这个表和订单项目注释表
-- 在连接条件里面,我们应该比较这两列和他们在订单项目注释表对应的列
select 
    oin.note,
    oi.quantity,
    oi.unit_price
from order_items oi
join order_item_notes oin
    # on oi.order_id = oin.order_id
    # and oi.product_id = oin.product_id
    using (order_id, product_id)

 2.11 自然连接

-- MySQL有更简单的方法连接两个表
-- 自然连接
-- 但是不推荐使用alter
USE SQL_STORE;

SELECT 
	o.order_id,
    c.first_name
FROM orders o
NATURAL JOIN customers c
-- 就这样直接连接,数据引擎会自己看着办,基于共同的列进行连接

 2.12 交叉连接

-- sql的交叉连接
-- 用交叉连接结合或者使用连接第一个表的每条记录和第二个表的每条记录
select 
	c.first_name as customer,
    p.name as product
from customers c
-- 顾客表的每条记录都会和产品表的记录结合
cross join products p
-- 所以这里也没有写条件是什么。
order by c.first_name  # 排个序
-- 结果介绍
-- 首先是Ambur和所有的产品进行组合方式
-- 但是,这里的交叉连接没有实际意义
-- 比如,你有一个型号表,大中小;颜色表:红黄绿
-- 所有的型号和颜色进行匹配组合,就可以使用

-- 此外,我们可以不直接把“交叉连接”打出来,而是在from后面加上表
select 
	c.first_name as cs,
    p.name as product
from customers c, products p
order by c.first_name

2.13 UNION联合

-- 我们可以使用连接可以结合多张表的列
-- 我们也可以结合多张表的行

/*
select 
	order_id,
    order_date,
    'activate' as status
from orders
-- 发现,只有一个是2019年下单的,其他的事前些年下的单
-- 建个报告,里面所有的订单边上添加一个标签
-- 今年的订单叫做activate,其他的叫做archive
where order_date >= '2019-01-01'

-- 没有使用union的时候,where后面的语句要加;
-- 有了union之后,就不要了
union

select 
	order_id,
    order_date,
    'archive' as status
from orders
where order_date <= '2019-01-01'


-- 在这里,两部分语句各自产生输出
-- 我们可以用union合并
*/

-- 上面的例子是在一张表内进行的
-- 也可以在不同的表进行联合

select first_name as full_name
from customers
union
select name
from shippers

-- 要注意的是,我们在联合输出结构的时候,select的内容
-- 需要是一样的,如何:一个出现2个,一个出现1个,那么就会报错了
-- 上面的内容,输出的结果是列名是“first_name”
-- 我们发现,输出列名是看第一个选择的是什么
-- 在上面,我们选择的是first_name,
-- 我们可以 select first_name as full_name