最后更新:2022.10.18
SELECT
DISTINCT director
FROM movies;
SELECT director
FROM movies
GROUP BY director;
从 num_offset 开始查找前 n 条数据。
# MySQL
SELECT *
FROM tablename
LIMIT n OFFSET num_offset;
限制条件可以更换为以下 SQL,表示取从 num_offset 开始前 n 条数据:
LIMIT num_offset, n
坑: num_offset 从 0 开始!
INNER JOIN 取两个集合的交集,也即自然连接:
SELECT *
FROM movies as m INNER JOIN Boxoffice as b
ON m.id = b.movie_id;
在表A 连接 B, LEFT JOIN 保留A的所有行,不管有没有能匹配上B 反过来 RIGHT JOIN 则保留所有 B 里的行。最后 FULL JOIN 不管有没有匹配上,同时保留 A 和 B 里的所有行。
找到所有有雇员的办公室(buildings)和对应的容量:
方法 1:LEFT JOIN
SELECT building, Capacity
FROM Buildings as b LEFT JOIN employees as e
ON b.Building_name = e.building
WHERE building IS NOT NULL
GROUP BY building;
方法 2:嵌套查询
SELECT DISTINCT building_name,Capacity
FROM Buildings
WHERE building_name IN (SELECT DISTINCT building
FROM Employees);
INNER JOIN:适用于两个表值都存在。
外连接:适用于附表中值可能存在 NULL 的情况。
INNER JOIN B:取交集LEFT JOIN B:取 A 全部,B 没有对应的值,则为 NULLRIGHT JOIN B:取 B 全部,A 没有对应的值,则为 NULLFULL JOIN B:取并集,彼此没有对应的值为 NULL上述 4 种的对应条件,在 ON 后填写。
WHERE col_name IS NOT NULL
SELECT Building
FROM employees
WHERE building IS NOT NULL
GROUP BY building;
GROUP BY 分组会自动根据我们分组的字段进行排序,默认升序。
在
GROUP BY分组语法中,我们知道数据库是先对数据做WHERE,然后对结果做分组,如果我们要对分组完的数据再筛选出几条如何办? (想一下按年份统计电影票房,要筛选出票房 > 100万的年份?)
HAVING语法将用来解决这个问题,他可以对分组之后的数据再做SELECT筛选。
SELECT group_by_column, AGG_FUNC(column_expression) AS aggregate_result_alias, …
FROM mytable
WHERE condition
GROUP BY column
HAVING group_condition;
按导演分组计算销售总额,求出平均销售额冠军(统计结果过滤掉只有单部电影的导演,列出导演名,总销量,电影数量,平均销量):
SELECT Director, SUM(Domestic_sales+International_sales) AS Total,
COUNT(*) AS CNT,
SUM(Domestic_sales+International_sales)/COUNT(*) AS Per_sales
FROM Movies INNER JOIN Boxoffice ON Movies.id = Boxoffice.movie_id
GROUP BY Director
HAVING CNT > 1
ORDER BY Per_sales DESC
LIMIT 1;
判断语句,选择结构:
CASE WHEN THEN ELSE ENDIF(condition, a, b)按角色分组算出每个角色按有办公室和没办公室的统计人数(列出角色,数量,有无办公室,注意一个角色如果部分有办公室,部分没有需分开统计)
SELECT Role,COUNT(*), CASE
WHEN Building IS NOT NULL THEN 1
ELSE 0 END AS inBuilding
FROM Employees
GROUP BY Role, Building;
SELECT stock_name, SUM(IF(operation='Buy', -price, price)) AS capital_gain_loss
FROM Stocks
GROUP BY stock_name;
找出每部电影和单部电影销售冠军之间的销售差,列出电影名,销售额差额:
SELECT Title,
(SELECT MAX(Domestic_sales + International_sales)
FROM Boxoffice) - Domestic_sales - International_sales AS maxSales
FROM Movies INNER JOIN Boxoffice ON Movies.id = Boxoffice.movie_id
GROUP BY Title;
584. 寻找用户推荐人
写一个查询语句,返回一个客户列表,列表中客户的推荐人的编号都 不是 2:
方法一(IS NULL),注意 NULL 不能用 = 或者 != 判定:
SELECT name
FROM customer
WHERE referee_id IS NULL
OR referee_id != 2;
方法二(IFNULL),IFNULL(x, y) 表示若 x 为 NULL 则返回 y,若 x 不为 NULL 返回 x:
SELECT name
FROM customer
WHERE IFNULL(referee_id, 0) != 2;
EXISTS 是只有 1 个参数的谓词,只需要在右侧书写 1 个参数,该参数通常都会是一个子查询。如果子查询返回任何行,EXISTS 子查询为 TRUE,若为空行则为 FALSE。
183. 从不订购的客户
SELECT Name AS Customers
FROM Customers AS c
WHERE NOT EXISTS (
SELECT 1 FROM orders AS o WHERE o.Customerid = c.id
);
177. 第N高的薪水
写 SQL 那么久,第一次用函数的写法:
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
SET N := N-1;
RETURN (
# Write your MySQL query statement below.
SELECT salary
FROM Employee
GROUP BY salary
ORDER BY salary DESC
LIMIT N, 1
);
END
SELECT score, DENSE_RANK() OVER (ORDER BY score DESC) AS 'rank'
FROM Scores;
千万别用直接相减的方式!!
直接相减会将时间拼接为一个十进制数,然后相减,然后导致结果错误,比如:
2021-10-01 11:00:05 - 2021-10-01 10:59:05 等同于 20211001110005 - 20211001105905 = 4100
正确的方式应该用:
TIMESTAMPDIFF(SECOND, start_time, end_time)
第一个参数可以设置的值:
FRAC_SECOND:表示间隔是毫秒,SECOND:秒,MINUTE:分钟,HOUR:小时,DAY:天,WEEK:星期,MONTH:月,QUARTER:季度,YEAR:年