sql語句常考知識點總結


 

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 |
+---------+
select email as Email from person group by email having count(email)>1
 
 
----------------------------------------------------------------------------------------

給定一個 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合用.
update salary set sex = case when sex='m' then 'f' when sex = 'f' then 'm' else sex end;
 
 
 
-----------------------------------------------------------------------------------------------------------------------------------------------------------

給定一個 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 |
+----+
SELECT 
  t1.`id` AS Id 
FROM
  weather AS t1,
  weather AS t2 
WHERE t1.`recorddate`  -  t2.`recorddate` = 1    #這樣的報錯,還是需要用日期函數處理一下.
  AND t2.temperature < t1.`temperature` ;
 
 
SELECT 
  t1.`id` AS Id 
FROM
  weather AS t1,
  weather AS t2 
WHERE  ADDDATE(t2.`recorddate`,1) = t1.`recorddate`
  AND t2.temperature < t1.`temperature` ;
 
SELECT 
  t1.`id` AS Id 
FROM
  weather AS t1,
  weather AS t2 
WHERE  datediff( t1.`recorddate`,t2.`recorddate`) =1
  AND t2.temperature < t1.`temperature` ;
 
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------

部門表 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(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
      WHEN MONTH = 'Jan' 
      THEN revenue 
      ELSE 'null' 
    END AS 'Jan_Revenue',
    CASE
      WHEN MONTH = 'Feb' 
      THEN revenue 
      ELSE 'null' 
    END AS 'Feb_Revenue',
    CASE
      WHEN MONTH = 'Mar' 
      THEN revenue 
      ELSE 'null' 
    END AS 'Mar_Revenue',
    CASE
      WHEN MONTH = 'Apr' 
      THEN revenue 
      ELSE 'null' 
    END AS 'Apr_Revenue',
    CASE
      WHEN MONTH = 'May' 
      THEN revenue 
      ELSE 'null' 
    END AS 'May_Revenue',
    CASE
      WHEN MONTH = 'Jun' 
      THEN revenue 
      ELSE 'null' 
    END AS 'Jun_Revenue',
    CASE
      WHEN MONTH = 'Jul' 
      THEN revenue 
      ELSE 'null' 
    END AS 'Jul_Revenue',
    CASE
      WHEN MONTH = 'Aug' 
      THEN revenue 
      ELSE 'null' 
    END AS 'Aug_Revenue',
    CASE
      WHEN MONTH = 'Sep' 
      THEN revenue 
      ELSE 'null' 
    END AS 'Sep_Revenue',
    CASE
      WHEN MONTH = 'Oct' 
      THEN revenue 
      ELSE 'null' 
    END AS 'Oct_Revenue',
    CASE
      WHEN MONTH = 'Nov' 
      THEN revenue 
      ELSE 'null' 
    END AS 'Nov_Revenue',
    CASE
      WHEN MONTH = 'Dec' 
      THEN revenue 
      ELSE 'null' 
    END AS 'Dec_Revenue' 
  FROM
    department) AS t1 
GROUP BY id ;
#以上是自己寫的,以下是官方給出的答案,上面自己 寫的沒有時輸出為0,不為空,不通過.

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    |
+-------+------+

SELECT 
  a.score AS score,
  (SELECT 
    COUNT(DISTINCT b.score) 
  FROM
    scores b 
  WHERE b.score >= a.score) AS Rank 
FROM
  scores a 
ORDER BY a.score DESC
 
--------------------------------------------------------------------------------------------------------------------------------------------------------------

編寫一個 SQL 查詢,獲取 Employee 表中第 n 高的薪水(Salary)。

+----+--------+
| Id | Salary |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+--------+
例如上述 Employee 表,n = 2 時,應返回第二高的薪水 200。如果不存在第 n 高的薪水,那么查詢應返回 null。

+------------------------+
| getNthHighestSalary(2) |
+------------------------+
| 200 |
+------------------------+

 

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
   set n = N - 1;
  RETURN (
      # Write your MySQL query statement below.
     SELECT 
   CASE
    WHEN 
    (SELECT 
       COUNT(*) 
    FROM
       (SELECT 
        DISTINCT salary 
      FROM
        Employee 
      ORDER BY salary DESC 
      LIMIT n, 1) AS a)  = 0 
     THEN NULL     #無記錄時mysql不是null,通過外面包一層count(*)=0加上case when判斷轉為無記錄時展示null
    ELSE 
    (SELECT  DISTINCT   #相同的工資,排名一樣.
      salary 
    FROM
      Employee 
    ORDER BY salary DESC 
    LIMIT n, 1) 
  END AS salary  
  );
END
以上是我自己的解法,下面是點贊最多的人的.看了人家寫的,覺得真是有差距啊55555,無論是思路還是語句都是有差距的.
思路 : 那么要先查出前N薪水,然后取最小就好了,注意可能總數不夠前N,count一下比較即可

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 ;

 以上是自己 寫的,思路: 先按部門分組,找出每個部門最高的工資,然后再連接自己 和部門表. where 條件中不能有聚合函數,group by的句子中select的字段只能是分組字段+ 聚合函數的字段.其它的字段查出來都是錯誤 的.下面是別的大牛的.

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()會選擇被分到同一組的數據里第一條數據的指定列值作為返回數據


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM