SELECT * FROM language WHERE EXISTS( SELECT * FROM film WHERE film.language_id = language.language_id ); SELECT * FROM language WHERE language_id IN ( SELECT DISTINCT language_id FROM film ); -- 使用 EXISTS 的语句的性能比对应的使用 IN 的语句要好。
ORDER BY:排序
升序排序时, NULL 在非 NULL 值之前;降序排序时,NULL 在非 NULL 值之后。
按多字段排序
SELECT actor_id, first_name, last_name FROM actor ORDER BY last_name DESC, first_name;
使用 CASE 实现自定义排序
SELECT film_id, title, rating FROM film ORDER BY CASE rating WHEN 'G' THEN 1 WHEN 'PG' THEN 2 WHEN 'PG-13' THEN 3 WHEN 'R' THEN 4 WHEN 'NC-17' THEN 5 END;
SELECT * FROM film ORDER BY FIELD(rating, 'G', 'PG', 'PG-13', 'R', 'NC-17');
TABLE
TABLE products SELECT * FROM products -- 等价
LIMIT:分页
LIMIT 子句限定查询返回的行数。
LIMIT 子句经常结合 ORDER BY 查询排名列表。
SELECT film_id, title, length FROM film WHERE rating = 'G' ORDER BY length LIMIT 10; -- limit 3, 4 跳过3行, 最多显示4行
DISTINCT:去重
SELECT DISTINCT last_name, first_name FROM actor;
多表查询
内连接
内连接基于连接条件组合两个表中的数据。
SELECT order_id, first_name, last_name, orders.customer_id FROM orders INNER JOIN customers -- INNER 可省略 ON orders.customer_id = customers.customer_id -- 等价(隐式连接,不推荐,会忘记where) FROM orders, customers WHERE orders.customer_id = customers.customer_id
表的别名:在表后空格写表的别名
SELECT order_id, first_name, last_name, o.customer_id FROM orders o JOIN customers c ON o.customer_id = c.customer_id
跨数据库连接
SELECT * FROM order_items oi JOIN sql_inventory.products p ON oi.product_id = p.product_id
自连接
两张一样的表进行连接
SELECT e.employee_id, e.first_name, m.first_name AS manager FROM employees e JOIN employees m ON e.reports_to = m.employee_id
多表连接
通过什么信息拿到什么信息
SELECT o.order_id, c.first_name, c.last_name, o.order_date, os.`name` FROM orders o JOIN customers c ON o.customer_id = c.customer_id -- 通过顾客id拿到顾客名字 JOIN order_statuses os ON o.`status` = os.order_status_id -- 通过status id拿到status 名字 ORDER BY order_id
外连接
内连接基于连接条件组合两个表中的数据。
外连接基于连接条件,对于不满足条件的用NULL作为数据补充
单表外连接
SELECT p.product_id, p.`name`, oi.quantity FROM products p LEFT JOIN order_items oi on p.product_id = oi.product_id -- USING(product_id) 等价
多表外连接
SELECT o.order_date, o.order_id, c.first_name, s.`name` AS shipper, os.`name` AS status FROM orders o JOIN customers c ON o.customer_id = c.customer_id LEFT JOIN shippers s on o.shipper_id = s.shipper_id JOIN order_statuses os on o.`status` = os.order_status_id ORDER BY status
USING:等值匹配
SELECT student.*, student_score.* FROM student JOIN student_score USING(student_id); -- 列名一样
交叉连接:笛卡尔积
SELECT student.*, student_score.* FROM student CROSS JOIN student_score; -- 等价 FROM student, student_score; -- 等价于无连接条件的内连接
自然连接
特殊的等值连接
SELECT o.order_id, c.first_name FROM orders o NATURAL JOIN customers c -- 基于相同列自动连接, 不建议使用
UNION
UNION 运算要求参与运算的两个结果集的列数必须一样。
UNION 运算取第一个参与运算的结果集的列名作为最终的列名。
SELECT customer_id, first_name, points, 'Bronze' AS type FROM customers WHERE points <= 2000 UNION SELECT customer_id, first_name, points, 'Silver' AS type FROM customers WHERE points BETWEEN 2000 AND 3000 UNION SELECT customer_id, first_name, points, 'Gold' AS type FROM customers WHERE points > 3000 ORDER BY first_name
Create
创建表
CREATE TABLE user ( id INT AUTO_INCREMENT, name VARCHAR(255) NOT NULL, age INT, birthday DATE, PRIMARY KEY (id) );
表复制创建
CREATE TABLE invoices_archive SELECT invoice_id, number, c.`name` client_name, invoice_total, payment_total, invoice_date, due_date, payment_date FROM invoices i JOIN clients c USING(client_id) WHERE payment_date IS NOT NULL;
SELECT date, pm.`name` payment_method, SUM(p.amount) total_payments FROM payments p JOIN invoices i USING(invoice_id) JOIN payment_methods pm ON p.payment_method = pm.payment_method_id GROUP BY date, payment_method -- 指定的分组字段 ORDER BY date
HAVING:对分组进行过滤
只能作用于在select结果集中出现的列
SELECT client_id, SUM(invoice_total) total_sales, COUNT(*) number_of_invoices FROM invoices GROUP BY client_id HAVING total_sales >= 500 AND number_of_invoices > 5
子查询
where中的子查询
SELECT * FROM employees WHERE salary > ( SELECT AVG(salary) FROM employees )
IN 子查询
SELECT * FROM clients WHERE client_id NOT IN ( SELECT DISTINCT client_id FROM invoices ) -- 等价 SELECT * FROM clients c LEFT JOIN invoices i USING(client_id) WHERE i.client_id IS NULL
ALL 子查询
SELECT * FROM invoices WHERE invoice_total > ALL ( -- 大于全部结果 SELECT invoice_total FROM invoices WHERE client_id = 3 )
ANY 子查询
SELECT * FROM invoices WHERE invoice_total > ANY ( -- 大于任意一个 等价于IN SELECT invoice_total FROM invoices WHERE client_id = 3 )
相关子查询
SELECT * FROM invoices i WHERE i.invoice_total > ( SELECT AVG(invoice_total) FROM invoices WHERE client_id = i.client_id )
EXISTS
SELECT * FROM products p WHERE NOT EXISTS ( SELECT * FROM order_items oi WHERE p.product_id = oi.product_id )
SELECT子查询
SELECT client_id, `name`, (SELECT SUM(invoice_total) FROM invoices WHERE client_id = c.client_id) total_sales, (SELECT AVG(invoice_total) FROM invoices) average, (SELECT total_sales - average) difference FROM clients c;
FROM子查询 派生表
派生表必须有别名
SELECT * FROM ( SELECT client_id, `name`, (SELECT SUM(invoice_total) FROM invoices WHERE client_id = c.client_id) total_sales, (SELECT AVG(invoice_total) FROM invoices) average, (SELECT total_sales - average) difference FROM clients c ) psb; -- 必须有别名
函数
数值函数
ROUND 四舍五入
select round(5.4962, 2); -- 保留两位小数四舍五入 5.50
条件函数
if
select if(age >= 25, '25岁及以上', '25岁以下') age_cut, count(*) number from user_profile group by age_cut;
case
select case when age < 25 or age is null then '25岁以下' when age >= 25 then '25岁及以上' else '...' end age_cut, count(*) number from user_profile group by age_cut;
日期函数
VIEW:视图
CREATE VIEW 创建
视图类似表的指针,可以当做表使用
CREATE VIEW clients_balance AS SELECT c.client_id, c.`name`, i.invoice_total - i.payment_total balance FROM clients c JOIN invoices i USING (client_id) GROUP BY client_id
DROP VIEW 删除
DROP VIEW clients_balance;
CREATE OR REPLACE VIEW 创建或更改
CREATE OR REPLACE VIEW clients_balance AS SELECT c.client_id, c.`name`, i.invoice_total - i.payment_total balance FROM clients c JOIN invoices i USING (client_id) GROUP BY client_id;
可更新视图
WITH CHECK OPTION
防止update或delete删除视图中的行
CREATE OR REPLACE VIEW clients_balance AS SELECT c.client_id, c.`name`, i.invoice_total - i.payment_total balance FROM clients c JOIN invoices i USING (client_id) WITH CHECK OPTION; -- 必须是可更新视图