本文主要是介绍什么是扎实的基本功?MySQL 基础知识看看你了解多少,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
本文首发于公众平台:腐烂的橘子
当前很多同学沉迷于“碎片化学习”,问题在于获取到的都是零碎的知识,没有体系化的知识框架,这对于练就扎实的基本功是极其不利的。
怎么办?这时要懂得中庸之道“慢即是快”的道理,系统学一遍,查漏补缺,不要觉得有些你知道就学不下去了,要耐得住性子,系统学习。
下面就来检验下这些知识点你是否都掌握了。
关于 join 的那些事
Inner join
冷知识:join = inner join
select order_id, orders.customer_id
from order
join customers
on orders.customer_id = customers.customer_id
多库连接
可以通过 join 关联其他库表,这是基本用法。
use sql_inventory;select *
from sql_store.order_items oi
join sql_inventory.products p
on oi.product_id = p.product_id
自连接
join 除了可以关联其他表,也可以关联自己。
use sql_hr;select a.account_id, a.account_name,b.account_id, b.account_name
from t_account_object a
join t_account_object bon a.parent_parent_id = b.account_id
连接超过两张表
不多解释,不断使用 join
就可以了。
use sql_invoicing;select *
from payments p
join clients c
on p.client_id = c.client_id
join payment_methods pm
on p.payment_
outer join
这几个等价的关系你了解吗?
- inner join 也可写作 join
- left outer join 也可写作 left join
- right outer join 也可写作 right outer join
using 怎么用
如果关联的字段名相同,using 可以代替 on。
selecto.order_id,c.first_name
from orders o
join customers cusing (customer_id)
join shippers shusing (shipper_id)
等价于:
selecto.order_id,c.first_name
from orders o
join customers con c.customer_id = o.customer_id
join shippers shon sh.shipper_id = o.shipper_id
如果需要多个字段,用逗号分隔:
select *
from order_items oi
join order_item_notes oinusing (order_id, product_id)
自然连接
引擎自己选择连接的列,不推荐使用,因为没有显示指明是怎么关联的。
select *
from order o
natual join customers c
交叉连接
返回两张表所有数据行的笛卡尔积,这个一般也不推荐,因为笛卡尔积是指数级别的。
select *
from customers c
cross join products p
order by c.first_name
等价于
select *
from customers c, orders o
order by c.first_name
union
合并两段查询结果。注意两段的列数要相同,下面写法会报错:
select first_name, last_name
from customers
union
select name
from shippers
因为第一段返回一列,第二段返回两列,以下是正确的:
select first_name
from customers
union
select name
from shippers
这里的列名是 first_name,不是 name,以第一段查询的列名为准
varchar 和 char 的区别
- varchar(50),保存 5 个字符,则没有其余空间
- char(50),保存 5 个字符,还有 45 个字符空闲
表的创建、更新、删除、查询
insert 一张表
如果插入其中几个字段,需要写字段,否则可以不写:
insert into orders(customer_id, order_date, status)
values (1, '2019-01-02', 1);
insert into order_items
values(LAST_INSERT_ID(), 1, 1, 2.95),(LAST_INSERT_ID(), 1, 2, 3.95)
第一个 SQL 加了字段名,第二个没有。
创建表复制
复制整张表:
create table orders_archived as
select * from orders
其中 select * from orders
称为子查询,可以替换成其他复杂的查询语句。
复制其中某几行,还是用 insert into
:
insert into orders_archived
select *
from orders
where order_date < '2024-01-01'
更新单行
可以设置单行为 null
update invoices
set payment_total = invoice_total * 0.5, payment_date = null
where invoice_id = 1
更新多行
设置 where 选中多行即可。
update 使用子查询
update invoices
set
payment_total = invoice_total * 1.2,
payment_date = due_date
where client_id in (select client_id from clientswhere state in ('CA', 'NY'))
你一定要知道的聚合函数
数值聚合函数
MAX()
:求最大值MIN()
:求最小值AVG()
:求平均值SUM()
:求和COUNT()
:求数量
having 和 where 区别
- where 在分组前筛选
- having 在分组后筛选
with rollup
select state,city,sum(invoice_total) as total_sales
from invoices i
join clients c using (client_id)
group by state, city with rollup
生成总计,不能再用 order by。
ALL 关键字
select *
from invoices
where invoice_total > ALL (select invoice_totalfrom invoiceswhere client_id = 3
)
all 和 max 可以替换,比如可以写成这样:
select *
from invoices
where invoice_total > (select max(invoice_total)from invoiceswhere client_id = 3
)
ANY 关键字
先看一段 SQL:
select *
from clients
where cliend_id in (select client_idfrom invoicesgroup by client_idhavind count(*) >= 2
)
用 any 可以这样写:
select *
from clients
where cliend_id = any (select client_idfrom invoicesgroup by client_idhavind count(*) >= 2
)
所以 in
等价于 = any
AVG
select *
from invoices
where invoice_total > (select AVG(invoice_total)from invoiceswhere client_id = i.client_id
)
exists
select *
from clients c
where exists (select client_idfrom invoiceswhere client_id = c.client_id
)
select 子句中的子查询
selectinvoice_id, invoice_total,(select avg(invoice_total)from invoice) as invoice_average,invoice_total - (select invoice_average) as difference
from invoices
数值函数
round(5.7345, 2)
,四舍五入 5.73truncate(5.7345, 2)
, 截断,5.73ceiling(5.7)
, 6floor(5.2)
, 5abs(-5.2)
, 5.2rand()
, 0-1 之间的随机值,如 0.6633075453930605
字符串函数
length('sky')
,3,字符串长度upper('sky')
, SKYlower('SKy')
, skyltrim(' sky ')
,skyrtrim('sky ')
, skytrim(' sky ')
, skyleft('Kindergarten', 4)
, Kindright('Kinderarara', 6)
, rararasubstring('Kindergarten', 3, 5)
, nderglocate('n', 'Kindergarten')
, 3locate('garten', 'Kindergarten')
, 7replace('Kindergarten', 'garten', 'garden')
, Kindergardenconcat('first', 'last')
, firstlast
日期函数
- now(), 2024-06-23 00:34:04
- curdate(), 2024-06-23
- curtime(), 00:34:30
- year(now()), 2024
- month(now()), 6
- day(now()), 23
- hour(now()), 0
- minute(now()), 35
- second(now()), 32
- dayname(now()), Sunday,字符串格式的星期数
- monthname(now()), June, 字符串格式的月份
- extract(year from now()), 2024,标准SQL,推荐使用
- date_format(now(), ‘%y’), 24,两位数年份
- date_format(now(), ‘%Y’), 2024,四位数年份
- date_format(now(), ‘%m’), 06,两位数月份
- date_format(now(), ‘%M’), June,月份名称
- time_format(now(), ‘%H:%i %p’), 00:36 AM
计算日期和时间
- date_add(now(), interval 1 day),返回明天的同一时间
- date_add(now(), interval 1 year),返回明年的同一时间
- date_sub(now(), interval -1 year),返回明年的同一时间
- datediff(‘2024-06-02 09:00’, ‘2024-06-07 17:00’), 5
- datediff(‘2024-06-07 17:00’, ‘2024-06-02 09:00’), -5
- time_to_sec(‘09:00’), 32400, 表示从零点流逝的秒数
- time_to_sec(‘09:00’) - time_to_sec(‘09:02’), -120
ifnull 和 coalesce
ifnull(shipper_id, 'Not assigned')
:如果 shipper_id 为空,返回 Not assigned。即返回非空值coalesce(shipper_id, comments, 'Not assigned')
:如果 shipper_id 为空,返回 comments,如果 comments,如果 为空,返回 Not assigned。即返回第一个非空值
if
语法:if(expression, first, second)
select
product_id, name,
count(*) as orders,
if (count(*) > 1, 'Many times', 'Once')
from products
join order_items using (product_id)
case
select
order_id,
casewhen year(order_date) = year(now()) then 'Active' when year(order_date) = year(now()) - 1 then 'Last Year' when year(order_date) = year(now()) - 1 then 'Archived'
else 'Future'
end as category
MySQL 视图
创建视图
假设我们要多次使用一个查询结果:
selectc.client_id, c.name, sum(invoice_total) as total_sales
from clients c
join invoices i using (client_id)
group by client_id, name
可以创建一个视图:
create view sales_by_client as
selectc.client_id, c.name, sum(invoice_total) as total_sales
from clients c
join invoices i using (client_id)
group by client_id, name
更改或删除视图
如果想修改视图,有两种办法:
- 先删除视图,再创建视图
- 更改视图(更方便)
先删除视图:
drop view sales_by_client
再创建视图:
create view sales_by_client as
selectc.client_id, c.name, sum(invoice_total) as total_sales
from clients c
join invoices i using (client_id)
group by client_id, name
或直接使用创建或替换视图,更推荐:
create or replace view sales_by_client as
selectc.client_id, c.name, sum(invoice_total) as total_sales
from clients c
join invoices i using (client_id)
group by client_id, name
可以把这段sql保存在.sql文件中,这样可以随时创建视图了。
with option check 子句
如果你先创建了视图,但你可能会使用 update 更新视图里的数据,但是视图展示的还是老数据,会造成数据不一致。为了解决这个问题,你可以在视图里添加 with option check
子句,当 update 会更新掉视图的数据时报错,从而解决数据不一致的问题。
create or replace view sales_by_client as
selectc.client_id, c.name, sum(invoice_total) as total_sales
from clients c
join invoices i using (client_id)
group by client_id, name
with check option
视图的优点是提供了一种抽象,减少了表结构变化带来的影响。
这篇关于什么是扎实的基本功?MySQL 基础知识看看你了解多少的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!