sql語句練習題:https://blog.csdn.net/byf0521hlyp/article/details/80224840
參考鏈接:https://cloud.tencent.com/developer/article/1157338
1。 聚合函數不能出現在where條件語句中。
2。 有group by 時,select 中出現的字段中只能有group by 的字段和聚合函數;
3。 在HAVING子句中可以使用聚合函數,但在WHERE子句中不能。
4。insert into插入多條記錄時,values后面跟多個括號,一個括號一條記錄,括號內不同字段之間用逗號分隔;
5。通配符: 下划線_:匹配任意一個字符
百分號%:匹配0個或多個字符
中括號[]:匹配中括號中任意一個字符
中括號加尖號[^]:不匹配中括號中小尖后的任意一個字符
其中 []和[^]一般都和 like連用。使用通配符的一般都是模糊查詢。
通過實踐下面的語句查詢不出結果,改成regexp可以。原因是mysql不支持這種寫法。
6。常用聚合函數除 COUNT(*) 外,其它函數在計算過程中均忽略NULL值 ,用 count(distinct <列名>) ????
count(*):相當於統計行數,包含NULL ,且不去重。
count(name):不包含NULL,不去重。
count(distinct name) :不包含NULL 且去重。
當count 與 group by 連用時,count是對 group by 結果的各個分組進行計數。 若group by 后面有兩個字段,filed A 、filed B ,按A 分成M組,按B 分成N 組,則count出來的就是M*N個組的統計結果.
7。where、group by 、having 的執行順序, 第一where對from出來的記錄進行篩選,然后group by 對where后的結果進行統計,最后having 再對group by后的結果進行篩選。
8。連接查詢:若一個查詢同時涉及到兩張或以上的表,則稱為連接查詢。包括:內連接、自連接、外連接。
內連接:使用內連接時,如果兩個表的相關字段滿足條件,則從兩個表中提取數據組成新的記錄。
FROM 表1 [INNER] JOIN 表2 ON <連接條件>
自連接:
外連接:
a
9。char 和 varchar的區別: 若某列數據類型為varchar(20),存字符串”Jone”時,只占用4個字節,而char(20)會在為填滿的空間中填寫空格。所以, varchar類型比char類型更節省空間,但它的開銷會大一些,處理速度也慢一些。因此,n值比較小(小於4),用char類型更好些
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
例句分析:
1。 查詢物理系和數學系每個系的學生人數。 select subject,count(*) from students where subject in ('物理','數學') group by subject;
2。查詢名字的第二個字為“小” 或“大” 的學生的詳細信息。 select * from studnets where name like '_[小大]%' mysql不支持
3。查詢不姓張的學生的詳細信息。 select * from students where name not like '張%'
4。查詢姓“張”、“李”的學生的詳細信息。 select * from students where name like '[李張]%' mysql不支持
5。查詢各科目的最高分和最低分。 select subject,max(grade),min(grade) from students group by subject;
6。查詢各科成績的最高分和最低分的人的名字及分數; 先按科目分組將各科的最高分和最低分查詢出來,外面包一層,查出各科最高最低分對應的人的姓名,最后結果中去重。
7。獲取每個學生的選課門數及平均成績。
編寫一個 SQL 查詢,獲取 Employee 表中第二高的薪水(Salary) 。
+----+--------+
| Id | Salary |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+--------+
例如上述 Employee 表,SQL查詢應該返回 200 作為第二高的薪水。如果不存在第二高的薪水,那么查詢應返回 null。
+---------------------+
| SecondHighestSalary |
+---------------------+
| 200 |
+---------------------+
解題思路:
1. 如果僅出現兩個人並列第一時,也是沒有第二高薪水的,此時也是需要返回null,所以需要去重.
2. 第二高,用到limit x,y.
3.如果查詢結果無返回值(查詢不到數據),可用 case when + count(*) 進行處理
正確答案如下:
SELECT
CASE
WHEN
(SELECT
COUNT(*)
FROM
(SELECT DISTINCT
salary
FROM
employee
ORDER BY salary DESC
LIMIT 1, 1) AS tab1) = 0
THEN NULL
ELSE
(SELECT DISTINCT
salary
FROM
employee
ORDER BY salary DESC
LIMIT 1, 1)
END AS 'SecondHighestSalary' ;
-------------------------------------------------------------------------------------------------------------------------------------------
Employee
表包含所有員工,他們的經理也屬於員工。每個員工都有一個 Id,此外還有一列對應員工的經理的 Id。
+----+-------+--------+-----------+ | Id | Name | Salary | ManagerId | +----+-------+--------+-----------+ | 1 | Joe | 70000 | 3 | | 2 | Henry | 80000 | 4 | | 3 | Sam | 60000 | NULL | | 4 | Max | 90000 | NULL | +----+-------+--------+-----------+
給定 Employee
表,編寫一個 SQL 查詢,該查詢可以獲取收入超過他們經理的員工的姓名。在上面的表格中,Joe 是唯一一個收入超過他的經理的員工。
+----------+ | Employee | +----------+ | Joe | +----------+
select a.name as employee from employee as a inner join employee as b on a.managerid=b.id and a.salary > b.salary
----------------------------------------------------------------------------------------------------------------------------------
編寫一個 SQL 查詢,查找 Person
表中所有重復的電子郵箱。
示例:
+----+---------+ | Id | Email | +----+---------+ | 1 | a@b.com | | 2 | c@d.com | | 3 | a@b.com | +----+---------+
根據以上輸入,你的查詢應返回以下結果:
+---------+ | Email | +---------+ | a@b.com | +---------+
給定一個 salary
表,如下所示,有 m = 男性 和 f = 女性 的值。交換所有的 f 和 m 值(例如,將所有 f 值更改為 m,反之亦然)。要求只使用一個更新(Update)語句,並且沒有中間的臨時表。
注意,您必只能寫一個 Update 語句,請不要編寫任何 Select 語句。
例如:
| id | name | sex | salary | |----|------|-----|--------| | 1 | A | m | 2500 | | 2 | B | f | 1500 | | 3 | C | m | 5500 | | 4 | D | f | 500 |
運行你所編寫的更新語句之后,將會得到以下表:
| id | name | sex | salary | |----|------|-----|--------| | 1 | A | f | 2500 | | 2 | B | m | 1500 | | 3 | C | f | 5500 | | 4 | D | m | 500 |
解題思路: update和case when合用.
給定一個 Weather
表,編寫一個 SQL 查詢,來查找與之前(昨天的)日期相比溫度更高的所有日期的 Id。
+---------+------------------+------------------+ | Id(INT) | RecordDate(DATE) | Temperature(INT) | +---------+------------------+------------------+ | 1 | 2015-01-01 | 10 | | 2 | 2015-01-02 | 25 | | 3 | 2015-01-03 | 20 | | 4 | 2015-01-04 | 30 | +---------+------------------+------------------+
例如,根據上述給定的 Weather
表格,返回如下 Id:
+----+ | Id | +----+ | 2 | | 4 | +----+
部門表 Department
:
+---------------+---------+ | Column Name | Type | +---------------+---------+ | id | int | | revenue | int | | month | varchar | +---------------+---------+ (id, month) 是表的聯合主鍵。 這個表格有關於每個部門每月收入的信息。 月份(month)可以取下列值 ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]。
編寫一個 SQL 查詢來重新格式化表,使得新的表中有一個部門 id 列和一些對應 每個月 的收入(revenue)列。
查詢結果格式如下面的示例所示:
Department 表: +------+---------+-------+ | id | revenue | month | +------+---------+-------+ | 1 | 8000 | Jan | | 2 | 9000 | Jan | | 3 | 10000 | Feb | | 1 | 7000 | Feb | | 1 | 6000 | Mar | +------+---------+-------+ 查詢得到的結果表: +------+-------------+-------------+-------------+-----+-------------+ | id | Jan_Revenue | Feb_Revenue | Mar_Revenue | ... | Dec_Revenue | +------+-------------+-------------+-------------+-----+-------------+ | 1 | 8000 | 7000 | 6000 | ... | null | | 2 | 9000 | null | null | ... | null | | 3 | null | 10000 | null | ... | null | +------+-------------+-------------+-------------+-----+-------------+ 注意,結果表有 13 列 (1個部門 id 列 + 12個月份的收入列)。
CREATE TABLE department (
id INT (10) NOT NULL,
revenue INT (10) NOT NULL,
MONTH VARCHAR (10) NOT NULL,
PRIMARY KEY (id,MONTH)
) ;
#插入數據
INSERT INTO department (id, revenue, MONTH)
VALUES
(1, 8000, 'Jan'),
(2, 9000, 'Jan'),
(3, 10000, 'Feb'),
(1, 7000, 'Feb'),
(1, 6000, 'Mar') ;
#查詢
SELECT id,
SUM(CASE `month` WHEN 'Jan' THEN revenue END) Jan_Revenue,
SUM(CASE `month` WHEN 'Feb' THEN revenue END) Feb_Revenue,
SUM(CASE `month` WHEN 'Mar' THEN revenue END) Mar_Revenue,
SUM(CASE `month` WHEN 'Apr' THEN revenue END) Apr_Revenue,
SUM(CASE `month` WHEN 'May' THEN revenue END) May_Revenue,
SUM(CASE `month` WHEN 'Jun' THEN revenue END) Jun_Revenue,
SUM(CASE `month` WHEN 'Jul' THEN revenue END) Jul_Revenue,
SUM(CASE `month` WHEN 'Aug' THEN revenue END) Aug_Revenue,
SUM(CASE `month` WHEN 'Sep' THEN revenue END) Sep_Revenue,
SUM(CASE `month` WHEN 'Oct' THEN revenue END) Oct_Revenue,
SUM(CASE `month` WHEN 'Nov' THEN revenue END) Nov_Revenue,
SUM(CASE `month` WHEN 'Dec' THEN revenue END) Dec_Revenue
FROM Department
GROUP BY id;
總結:以后自己 寫的長的SQL 語句,多思考一下如何簡化. 以下是自己寫的將返回的0改為null
SELECT
id,
SUM(Jan_revenue) AS 'Jan_Revenue',
SUM(Feb_revenue) AS 'Feb_revenue',
SUM(Mar_revenue) AS 'Mar_revenue',
SUM(Apr_revenue) AS 'Apr_revenue',
SUM(May_revenue) AS 'May_revenue',
SUM(Jun_revenue) AS 'Jun_revenue',
SUM(Jul_revenue) AS 'Jul_revenue',
SUM(Aug_revenue) AS 'Aug_revenue',
SUM(Sep_revenue) AS 'Sep_revenue',
SUM(Oct_revenue) AS 'Oct_revenue',
SUM(Nov_revenue) AS 'Nov_revenue',
SUM(Dec_revenue) AS 'Dec_revenue'
FROM
(SELECT
id,
CASE MONTH
WHEN'Jan'
THEN revenue
END AS 'Jan_Revenue',
CASE MONTH
WHEN 'Feb'
THEN revenue
END AS 'Feb_Revenue',
CASE MONTH
WHEN 'Mar'
THEN revenue
END AS 'Mar_Revenue',
CASE MONTH
WHEN 'Apr'
THEN revenue
END AS 'Apr_Revenue',
CASE MONTH
WHEN 'May'
THEN revenue
END AS 'May_Revenue',
CASE MONTH
WHEN 'Jun'
THEN revenue
END AS 'Jun_Revenue',
CASE MONTH
WHEN 'Jul'
THEN revenue
END AS 'Jul_Revenue',
CASE MONTH
WHEN 'Aug'
THEN revenue
END AS 'Aug_Revenue',
CASE MONTH
WHEN 'Sep'
THEN revenue
END AS 'Sep_Revenue',
CASE MONTH
WHEN 'Oct'
THEN revenue
END AS 'Oct_Revenue',
CASE MONTH
WHEN 'Nov'
THEN revenue
END AS 'Nov_Revenue',
CASE MONTH
WHEN 'Dec'
THEN revenue
END AS 'Dec_Revenue'
FROM
department) AS t1
GROUP BY id ;
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
某城市開了一家新的電影院,吸引了很多人過來看電影。該電影院特別注意用戶體驗,專門有個 LED顯示板做電影推薦,上面公布着影評和相關電影描述。
作為該電影院的信息部主管,您需要編寫一個 SQL查詢,找出所有影片描述為非 boring
(不無聊) 的並且 id 為奇數 的影片,結果請按等級 rating
排列。
例如,下表 cinema
:
+---------+-----------+--------------+-----------+ | id | movie | description | rating | +---------+-----------+--------------+-----------+ | 1 | War | great 3D | 8.9 | | 2 | Science | fiction | 8.5 | | 3 | irish | boring | 6.2 | | 4 | Ice song | Fantacy | 8.6 | | 5 | House card| Interesting| 9.1 | +---------+-----------+--------------+-----------+
對於上面的例子,則正確的輸出是為:
+---------+-----------+--------------+-----------+ | id | movie | description | rating | +---------+-----------+--------------+-----------+ | 5 | House card| Interesting| 9.1 | | 1 | War | great 3D | 8.9 | +---------+-----------+--------------+-----------+
#建表
CREATE TABLE cinema (
id INT (10) NOT NULL AUTO_INCREMENT,
movie VARCHAR (10) NOT NULL,
description VARCHAR (30) NOT NULL,
rating FLOAT NOT NULL,
PRIMARY KEY (id));
#插入
INSERT INTO cinema (movie, description, rating)
VALUES
('war', 'great 3D', 8.9),
('science', 'fiction 3D', 8.5),
('irish', 'boring 3D', 6.2),
('ice song', 'fantacy 3D', 8.6),
('house card', 'interesting', 9.1) ;
#查詢
SELECT
*
FROM
cinema
WHERE description NOT LIKE '%boring%' AND MOD(id,2) = 1
ORDER BY rating DESC ;
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
某網站包含兩個表,Customers
表和 Orders
表。編寫一個 SQL 查詢,找出所有從不訂購任何東西的客戶。
Customers
表:
+----+-------+ | Id | Name | +----+-------+ | 1 | Joe | | 2 | Henry | | 3 | Sam | | 4 | Max | +----+-------+
Orders
表:
+----+------------+ | Id | CustomerId | +----+------------+ | 1 | 3 | | 2 | 1 | +----+------------+
例如給定上述表格,你的查詢應返回:
+-----------+ | Customers | +-----------+ | Henry | | Max | +-----------+
#建表
CREATE TABLE customers (
id INT (10) NOT NULL AUTO_INCREMENT,
NAME VARCHAR (20) NOT NULL,
PRIMARY KEY (id)
) ;
CREATE TABLE orders (
id INT (10) NOT NULL AUTO_INCREMENT,
customerid INT(10) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (customerid) REFERENCES customers(id)
) ;
#插入數據
INSERT INTO customers (NAME) VALUES ('Joe'),('Henry'),('Sam'),('Max');
INSERT INTO orders (customerid) VALUES (3),(1);
#查詢語句
SELECT
NAME AS Customers
FROM
customers
WHERE id NOT IN
(SELECT
a.id
FROM
customers a
INNER JOIN orders b
ON a.id = b.`customerid`);
下面是官方給的. 精典. 感覺自己寫那么多廢話.5555555555555.
select customers.name as 'Customers'
from customers
where customers.id not in
(
select customerid from orders
);
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
表1: Person
+-------------+---------+ | 列名 | 類型 | +-------------+---------+ | PersonId | int | | FirstName | varchar | | LastName | varchar | +-------------+---------+ PersonId 是上表主鍵
表2: Address
+-------------+---------+ | 列名 | 類型 | +-------------+---------+ | AddressId | int | | PersonId | int | | City | varchar | | State | varchar | +-------------+---------+ AddressId 是上表主鍵
編寫一個 SQL 查詢,滿足條件:無論 person 是否有地址信息,都需要基於上述兩表提供 person 的以下信息:
FirstName, LastName, City, State
#建表
create table person
(personid int(10) not null auto_increment,
firstname varchar(30) not null,
lastname varchar(30) not null,
primary key(personid));
create table address
(addressid int(10) not null auto_increment,
personid int(10) not null,
city varchar(30) not null,
state varchar(30) not null,
primary key (addressid));
#插入數據
insert into person (firstname,lastname) values('wang','min'),('li','yuerong'),('li','fengyan');
insert into address (personid,city,state) values(1,'changzhi','1'),(2,'yangquan','0');
#查詢
select firstname,lastname,city,state from person a left join address b on a.personid = b.`personid`;
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
有一個courses
表 ,有: student (學生) 和 class (課程)。
請列出所有超過或等於5名學生的課。
例如,表:
+---------+------------+ | student | class | +---------+------------+ | A | Math | | B | English | | C | Math | | D | Biology | | E | Math | | F | Computer | | G | Math | | H | Math | | I | Math | +---------+------------+
應該輸出:
+---------+ | class | +---------+ | Math | +---------+
Note:
學生在每個課中不應被重復計算。
解答:
#建表
CREATE TABLE courses (student VARCHAR(5) NOT NULL,class VARCHAR(10) NOT NULL);
#插入數據
INSERT INTO courses (student,class) VALUES
('A','Math'),
('B','English'),
('C','Math'),
('D','Biology'),
('E','Math'),
('F','Computer'),
('G','Math'),
('H','Math'),
('I','Math');
#查詢
SELECT class FROM courses GROUP BY class HAVING COUNT(distinct student)>=5;
select class,count(distinct student) from courses group by class;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
編寫一個 SQL 查詢來實現分數排名。如果兩個分數相同,則兩個分數排名(Rank)相同。請注意,平分后的下一個名次應該是下一個連續的整數值。換句話說,名次之間不應該有“間隔”。
+----+-------+ | Id | Score | +----+-------+ | 1 | 3.50 | | 2 | 3.65 | | 3 | 4.00 | | 4 | 3.85 | | 5 | 4.00 | | 6 | 3.65 | +----+-------+
例如,根據上述給定的 Scores
表,你的查詢應該返回(按分數從高到低排列):
+-------+------+ | Score | Rank | +-------+------+ | 4.00 | 1 | | 4.00 | 1 | | 3.85 | 2 | | 3.65 | 3 | | 3.65 | 3 | | 3.50 | 4 | +-------+------+
編寫一個 SQL 查詢,獲取 Employee 表中第 n 高的薪水(Salary)。
+----+--------+
| Id | Salary |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+--------+
例如上述 Employee 表,n = 2 時,應返回第二高的薪水 200。如果不存在第 n 高的薪水,那么查詢應返回 null。
+------------------------+
| getNthHighestSalary(2) |
+------------------------+
| 200 |
+------------------------+
select
if(cnt < N, null, min) as getNthHighestSalary
from
(select
min(salary) as min,
count(1) as cnt
from
(select distinct
salary
from
Employee
order by salary desc
limit N) as a) as b;
小美是一所中學的信息科技老師,她有一張 seat
座位表,平時用來儲存學生名字和與他們相對應的座位 id。
其中縱列的 id 是連續遞增的
小美想改變相鄰倆學生的座位。
你能不能幫她寫一個 SQL query 來輸出小美想要的結果呢?
示例:
+---------+---------+ | id | student | +---------+---------+ | 1 | Abbot | | 2 | Doris | | 3 | Emerson | | 4 | Green | | 5 | Jeames | +---------+---------+
假如數據輸入的是上表,則輸出結果如下:
+---------+---------+ | id | student | +---------+---------+ | 1 | Doris | | 2 | Abbot | | 3 | Green | | 4 | Emerson | | 5 | Jeames | +---------+---------+
注意:
如果學生人數是奇數,則不需要改變最后一個同學的座位。
#建表
CREATE TABLE seat (id INT(10) NOT NULL AUTO_INCREMENT,student VARCHAR(20) NOT NULL,PRIMARY KEY(id));
#插入
INSERT INTO seat (student) VALUES ("Abbot"),("Doris"),("Emerson"),("Green"),("Jeames");
#換座位 思路: ID為偶數時,變成本身減1, 如果為奇數時,變成本身加1, 但當ID為奇數且為最后一個(= count)時,就還是本身..
SELECT IF(id%2=0,id-1,IF(id=cnt,id,id+1)) AS id,student FROM (SELECT COUNT(*) AS cnt FROM seat)AS a,seat ORDER BY id;
SELECT IF(id%2=0,id-1,id(id=cnt,id,id+1)) AS id,student FROM (SELECT COUNT(*) AS cnt FROM seat) AS a,seat;
SELECT id,student,cnt FROM (SELECT COUNT(*) AS cnt FROM seat) AS a,seat ORDER BY id DESC;
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
部門工資最高的員工:
Employee
表包含所有員工信息,每個員工有其對應的 Id, salary 和 department Id。
+----+-------+--------+--------------+ | Id | Name | Salary | DepartmentId | +----+-------+--------+--------------+ | 1 | Joe | 70000 | 1 | | 2 | Henry | 80000 | 2 | | 3 | Sam | 60000 | 2 | | 4 | Max | 90000 | 1 | +----+-------+--------+--------------+
Department
表包含公司所有部門的信息。
+----+----------+ | Id | Name | +----+----------+ | 1 | IT | | 2 | Sales | +----+----------+
編寫一個 SQL 查詢,找出每個部門工資最高的員工。例如,根據上述給定的表格,Max 在 IT 部門有最高工資,Henry 在 Sales 部門有最高工資。
+------------+----------+--------+ | Department | Employee | Salary | +------------+----------+--------+ | IT | Max | 90000 | | Sales | Henry | 80000 | +------------+----------+--------+
#建表
CREATE TABLE Employee1 (id INT(10) NOT NULL AUTO_INCREMENT,NAME VARCHAR(10) NOT NULL,salary INT(10) NOT NULL,departmentid INT(10) NOT NULL,PRIMARY KEY(id));
CREATE TABLE Department (id INT(10) NOT NULL AUTO_INCREMENT,NAME VARCHAR(10) NOT NULL,PRIMARY KEY(id));
#插入
INSERT INTO Employee1 (NAME,salary,departmentid) VALUES ("Joe",70000,1),("Henry",80000,2),("Sam",60000,2),("Max",90000,1);
INSERT INTO Department (NAME) VALUES("IT"),("Sales");
#部門最高工資
SELECT
b.departmentname AS department,
a.name AS employee,
a.`salary`
FROM
Employee1 AS a
INNER JOIN
(SELECT
MAX(c.salary) AS salary,
c.departmentid,
d.`name` AS departmentname
FROM
Employee1 AS c INNER JOIN Department AS d ON c.`departmentid`=d.`id`
GROUP BY c.departmentid) AS b
ON a.`salary` = b.salary
AND a.`departmentid` = b.departmentid ORDER BY a.`salary` DESC ;
SELECT
Department.name AS 'Department',
Employee.name AS 'Employee',
Salary
FROM
Employee
JOIN
Department ON Employee.DepartmentId = Department.Id
WHERE
(Employee.DepartmentId , Salary) IN
( SELECT
DepartmentId, MAX(Salary)
FROM
Employee
GROUP BY DepartmentId
)
官方答案思路清晰,且條件是兩個字段in一個子查詢輸出的兩個字段. 即, where a,b in (select c,d from table); 這樣的格式頭一次見到,學習了.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Trips
表中存所有出租車的行程信息。每段行程有唯一鍵 Id,Client_Id 和 Driver_Id 是 Users
表中 Users_Id 的外鍵。Status 是枚舉類型,枚舉成員為 (‘completed’, ‘cancelled_by_driver’, ‘cancelled_by_client’)。
+----+-----------+-----------+---------+--------------------+----------+ | Id | Client_Id | Driver_Id | City_Id | Status |Request_at| +----+-----------+-----------+---------+--------------------+----------+ | 1 | 1 | 10 | 1 | completed |2013-10-01| | 2 | 2 | 11 | 1 | cancelled_by_driver|2013-10-01| | 3 | 3 | 12 | 6 | completed |2013-10-01| | 4 | 4 | 13 | 6 | cancelled_by_client|2013-10-01| | 5 | 1 | 10 | 1 | completed |2013-10-02| | 6 | 2 | 11 | 6 | completed |2013-10-02| | 7 | 3 | 12 | 6 | completed |2013-10-02| | 8 | 2 | 12 | 12 | completed |2013-10-03| | 9 | 3 | 10 | 12 | completed |2013-10-03| | 10 | 4 | 13 | 12 | cancelled_by_driver|2013-10-03| +----+-----------+-----------+---------+--------------------+----------+
Users
表存所有用戶。每個用戶有唯一鍵 Users_Id。Banned 表示這個用戶是否被禁止,Role 則是一個表示(‘client’, ‘driver’, ‘partner’)的枚舉類型。
+----------+--------+--------+ | Users_Id | Banned | Role | +----------+--------+--------+ | 1 | No | client | | 2 | Yes | client | | 3 | No | client | | 4 | No | client | | 10 | No | driver | | 11 | No | driver | | 12 | No | driver | | 13 | No | driver | +----------+--------+--------+
寫一段 SQL 語句查出 2013年10月1日 至 2013年10月3日 期間非禁止用戶的取消率。基於上表,你的 SQL 語句應返回如下結果,取消率(Cancellation Rate)保留兩位小數。
取消率的計算方式如下:(被司機或乘客取消的非禁止用戶生成的訂單數量) / (非禁止用戶生成的訂單總數)
+------------+-------------------+ | Day | Cancellation Rate | +------------+-------------------+ | 2013-10-01 | 0.33 | | 2013-10-02 | 0.00 | | 2013-10-03 | 0.50 | +------------+-------------------+
#建表
CREATE TABLE Trips1 (
id INT (10) NOT NULL AUTO_INCREMENT,
client_id INT (10) NOT NULL,
driver_id INT (10) NOT NULL,
city_id INT (10) NOT NULL,
STATUS VARCHAR (30) NOT NULL,
request_at DATETIME DEFAULT NULL,
PRIMARY KEY(id),
FOREIGN KEY(client_id) REFERENCES Users(users_id),
FOREIGN KEY(driver_id) REFERENCES Users(users_id));
CREATE TABLE Users (
users_id INT (10) NOT NULL AUTO_INCREMENT,
banned VARCHAR (10) NOT NULL,
role VARCHAR (10) NOT NULL,
PRIMARY KEY (users_id)
) ;
#插入
INSERT INTO Trips (client_id,driver_id,city_id,STATUS,request_at) VALUES
(1,10,1,"completed","2013-10-01"),
(2,11,1,"cancelled_by_driver","2013-10-01"),
(3,12,6,"completed","2013-10-01"),
(4,13,6,"cancelled_by_client","2013-10-01"),
(1,10,1,"completed","2013-10-02"),
(2,11,6,"completed","2013-10-02"),
(3,12,6,"completed","2013-10-02"),
(2,12,12,"completed","2013-10-03"),
(3,10,12,"completed","2013-10-03"),
(4,13,12,"cancelled_by_driver","2013-10-03");
INSERT INTO Users (users_id,banned,role) VALUES
(1,"No","client"),
(2,"Yes","client"),
(3,"No","client"),
(4,"No","client"),
(10,"No","driver"),
(11,"No","driver"),
(12,"No","driver"),
(13,"No","driver")
;
#行程和用戶
SELECT DATE(T.request_at) AS 'Day',
ROUND(SUM(IF(T.status ='completed',0,1))/COUNT(T.status),2) AS 'Cancellation Rate'
FROM Trips AS T
INNER JOIN Users AS U1 ON (T.client_id = U1.users_id AND U1.banned ='No')
INNER JOIN Users AS U2 ON (T.driver_id = U2.users_id AND U2.banned ='No')
WHERE T.request_at BETWEEN '2013-10-01' AND '2013-10-03'
GROUP BY T.request_at;
認識any_value()
#mysql中select后面跟的字段,必須在group by中出現,但有一個函數,可以將group by 中沒有出現的字段,在select后面帶出來,
這個函數就是any_value()
用法如下:
總結:
1.MySQL5.7之后,sql_mode中ONLY_FULL_GROUP_BY模式默認設置為打開狀態。
2.ONLY_FULL_GROUP_BY的語義就是確定select target list中的所有列的值都是明確語義,簡單的說來,在此模式下,target list中的值要么是來自於聚合函數(sum、avg、max等)的結果,要么是來自於group by list中的表達式的值
3.MySQL提供了any_value()函數來抑制ONLY_FULL_GROUP_BY值被拒絕
4.any_value()會選擇被分到同一組的數據里第一條數據的指定列值作為返回數據