day 39 MySQL之多表查詢

返回主頁

MySQL之多表查詢

 

一 介紹

  本節主題mysql

  • 多表鏈接查詢
  • 複合條件鏈接查詢
  • 子查詢

  首先說一下,咱們寫項目通常都會建一個數據庫,那數據庫裏面是否是存了好多張表啊,不可能把全部的數據都放到一張表裏面,確定要分表來存數據,這樣節省空間,數據的組織結構更清晰,解耦和程度更高,可是這些表本質上是否是仍是一個總體啊,是一個項目全部的數據,那既然分表存了,就要涉及到多個錶鏈接查詢了,好比說員工信息一張表,部門信息一張表,那若是我想讓你幫我查一下技術部門有哪些員工的姓名,你怎麼辦,單獨找員工表能實現嗎,不能,單獨找部門表也沒法實現,由於部門表裏面沒有員工的信息,對不對,因此就涉及到部門表和員工表來關聯到一塊兒進行查詢了,好,那咱們來創建這麼兩張表:sql

複製代碼
#建表
#部門表 create table department( id int, name varchar(20) );
#員工表,以前咱們學過foreign key,強行加上約束關聯,可是我下面這個表並無直接加foreign key,這兩個表我只是讓它們在邏輯意義上有關係,並無加foreign key來強制兩表創建關係,爲何要這樣搞,是有些效果要給你們演示一下
#因此,這兩個表是否是先創建哪一個表都行啊,若是有foreign key的話,是否是就須要注意表創建的順序了。那咱們來建表。 create table employee( id int primary key auto_increment, name varchar(20), sex enum('male','female') not null default 'male', age int, dep_id int ); #給兩個表插入一些數據 insert into department values (200,'技術'), (201,'人力資源'), (202,'銷售'), (203,'運營'); #注意這一條數據,在下面的員工表裏面沒有對應這個部門的數據 insert into employee(name,sex,age,dep_id) values ('egon','male',18,200), ('alex','female',48,201), ('wupeiqi','male',38,201), ('yuanhao','female',28,202), ('liwenzhou','male',18,200), ('jingliyang','female',18,204) #注意這條數據的dep_id字段的值,這個204,在上面的部門表裏面也沒有對應的部門id。因此二者都含有一條雙方沒有涉及到的數據,這都是爲了演示一下效果設計的昂 ; #查看錶結構和數據 mysql> desc department; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | name | varchar(20) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ mysql> desc employee; +--------+-----------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------+-----------------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | YES | | NULL | | | sex | enum('male','female') | NO | | male | | | age | int(11) | YES | | NULL | | | dep_id | int(11) | YES | | NULL | | +--------+-----------------------+------+-----+---------+----------------+ mysql> select * from department; +------+--------------+ | id | name | +------+--------------+ | 200 | 技術 | | 201 | 人力資源 | | 202 | 銷售 | | 203 | 運營 | +------+--------------+ mysql> select * from employee; +----+------------+--------+------+--------+ | id | name | sex | age | dep_id | +----+------------+--------+------+--------+ | 1 | egon | male | 18 | 200 | | 2 | alex | female | 48 | 201 | | 3 | wupeiqi | male | 38 | 201 | | 4 | yuanhao | female | 28 | 202 | | 5 | liwenzhou | male | 18 | 200 | | 6 | jingliyang | female | 18 | 204 | +----+------------+--------+------+--------+
複製代碼

 

二 多表鏈接查詢

#重點:外連接語法

SELECT 字段列表
    FROM 表1 INNER|LEFT|RIGHT JOIN 表2
    ON 表1.字段 = 表2.字段;

 

  一、交叉鏈接:不適用任何匹配條件。生成笛卡爾積數據庫

  

  補充一點:select 查詢表的時候,後面能夠跟多張表一塊兒查詢:windows

複製代碼
mysql> select * from department,employee; #表用逗號分隔,看我查詢時表的順序,先department後employee,因此你看結果表的這些字段,是否是就是咱們兩個表字段而且哪一個表在前面,哪一個表的字段就在前面
+------+--------------+----+------------+--------+------+--------+
| id   | name         | id | name       | sex    | age  | dep_id |
+------+--------------+----+------------+--------+------+--------+
|  200 | 技術         |  1 | egon       | male   |   18 |    200 |
|  201 | 人力資源     |  1 | egon       | male   |   18 |    200 |
|  202 | 銷售         |  1 | egon       | male   |   18 |    200 |
|  203 | 運營         |  1 | egon       | male   |   18 |    200 |
|  200 | 技術         |  2 | alex       | female |   48 |    201 |
|  201 | 人力資源     |  2 | alex       | female |   48 |    201 |
|  202 | 銷售         |  2 | alex       | female |   48 |    201 |
|  203 | 運營         |  2 | alex       | female |   48 |    201 |
|  200 | 技術         |  3 | wupeiqi    | male   |   38 |    201 |
|  201 | 人力資源     |  3 | wupeiqi    | male   |   38 |    201 |
|  202 | 銷售         |  3 | wupeiqi    | male   |   38 |    201 |
|  203 | 運營         |  3 | wupeiqi    | male   |   38 |    201 |
|  200 | 技術         |  4 | yuanhao    | female |   28 |    202 |
|  201 | 人力資源     |  4 | yuanhao    | female |   28 |    202 |
|  202 | 銷售         |  4 | yuanhao    | female |   28 |    202 |
|  203 | 運營         |  4 | yuanhao    | female |   28 |    202 |
|  200 | 技術         |  5 | liwenzhou  | male   |   18 |    200 |
|  201 | 人力資源     |  5 | liwenzhou  | male   |   18 |    200 |
|  202 | 銷售         |  5 | liwenzhou  | male   |   18 |    200 |
|  203 | 運營         |  5 | liwenzhou  | male   |   18 |    200 |
|  200 | 技術         |  6 | jingliyang | female |   18 |    204 |
|  201 | 人力資源     |  6 | jingliyang | female |   18 |    204 |
|  202 | 銷售         |  6 | jingliyang | female |   18 |    204 |
|  203 | 運營         |  6 | jingliyang | female |   18 |    204 |
+------+--------------+----+------------+--------+------+--------+
24 rows in set (0.12 sec)

咱們讓employee表在前面看看結果,注意看結果表的字段

mysql> select * from employee,department;
+----+------------+--------+------+--------+------+--------------+
| id | name | sex | age | dep_id | id | name |
+----+------------+--------+------+--------+------+--------------+
| 1 | egon | male | 18 | 200 | 200 | 技術 |
| 1 | egon | male | 18 | 200 | 201 | 人力資源 |
| 1 | egon | male | 18 | 200 | 202 | 銷售 |
| 1 | egon | male | 18 | 200 | 203 | 運營 |
| 2 | alex | female | 48 | 201 | 200 | 技術 |
| 2 | alex | female | 48 | 201 | 201 | 人力資源 |
| 2 | alex | female | 48 | 201 | 202 | 銷售 |
| 2 | alex | female | 48 | 201 | 203 | 運營 |
| 3 | wupeiqi | male | 38 | 201 | 200 | 技術 |
| 3 | wupeiqi | male | 38 | 201 | 201 | 人力資源 |
| 3 | wupeiqi | male | 38 | 201 | 202 | 銷售 |
| 3 | wupeiqi | male | 38 | 201 | 203 | 運營 |
| 4 | yuanhao | female | 28 | 202 | 200 | 技術 |
| 4 | yuanhao | female | 28 | 202 | 201 | 人力資源 |
| 4 | yuanhao | female | 28 | 202 | 202 | 銷售 |
| 4 | yuanhao | female | 28 | 202 | 203 | 運營 |
| 5 | liwenzhou | male | 18 | 200 | 200 | 技術 |
| 5 | liwenzhou | male | 18 | 200 | 201 | 人力資源 |
| 5 | liwenzhou | male | 18 | 200 | 202 | 銷售 |
| 5 | liwenzhou | male | 18 | 200 | 203 | 運營 |
| 6 | jingliyang | female | 18 | 204 | 200 | 技術 |
| 6 | jingliyang | female | 18 | 204 | 201 | 人力資源 |
| 6 | jingliyang | female | 18 | 204 | 202 | 銷售 |
| 6 | jingliyang | female | 18 | 204 | 203 | 運營 |
+----+------------+--------+------+--------+------+--------------+
24 rows in set (0.00 sec)post


關於笛卡兒積:咱們看一下上面的這些數據,有什麼發現,首先看到這些字段都顯示出來了,而且數據變得不少,咱們來看一下,這麼多條數據都是怎麼來的,爲何會出現這麼條數據,笛卡兒積這是一個數據名詞,你能夠去研究研究~~

  由於咱們要進行連表查詢,那麼mysql並不知道你想要如何鏈接兩個表的關係進行查詢,那麼mysql會將你兩個表數據的全部組合關係都給你拼接成一條數據來顯示,這樣你就能夠想查哪一個關聯關係的數據就查哪一個了,若是仍是不太理解看一下下面的圖:

複製代碼

 

  
  關於笛卡兒積現象的解釋圖:編碼

    

  

    我們爲了更好的管理數據,爲了節省空間,爲了數據組織結構更清晰,將數據拆分到了不一樣表裏面,可是本質上是否是仍是一份數據,一份重複內容不少的很大的數據,因此咱們即使是分表了,可是我們是否是還須要找到一個方案把兩個原本分開的表可以合併到一塊兒來進行查詢,那你是否是就能夠根據部門找員工,根據員工找部門了,對不對,可是咱們合併兩個表的時候,如何合併,根據什麼來合併,經過笛卡兒積這種合併有沒有浪費,咱們其實想作的是否是說咱們的員工表中dep_id這個字段中的數據和部門表裏面的id可以對應上就能夠了,由於咱們知道咱們設計表的時候,是經過這兩個字段來給兩個表創建關係的,對不對,看下圖:spa

    

    咱們的目標就是將兩個分散出去的表,按照二者之間有關係的字段,能對應上的字段,把二者合併成一張表,這就是多表查詢的一個本質。那麼笛卡兒積幹了什麼事兒,就是簡單粗暴的將兩個表的數據所有對應了一遍,用處就是什麼呢,它確定就能保證有一條是對應準的,你須要作的事情就是在笛卡兒積的基礎上只過濾出咱們須要的那些數據就好了,笛卡兒積不是我們最終要獲得的結果,只是給你提供了一個基礎,它無論對應的對不對,所有給你對應一遍,而後你本身去篩選就能夠了,而後基於笛卡兒積咱們來找一下對應的數據,看看能不能找到:設計

  二、內鏈接:只鏈接匹配的行code

複製代碼
#咱們要找的數據就是員工表裏面dep_id字段的值和部門表裏面id字段的值能對應上的那些數據啊,因此你看下面的寫法:
mysql> select * from employee,department where employee.dep_id=department.id;
+----+-----------+--------+------+--------+------+--------------+
| id | name      | sex    | age  | dep_id | id   | name         |
+----+-----------+--------+------+--------+------+--------------+
|  1 | egon      | male   |   18 |    200 |  200 | 技術         |
|  2 | alex      | female |   48 |    201 |  201 | 人力資源     |
|  3 | wupeiqi   | male   |   38 |    201 |  201 | 人力資源     |
|  4 | yuanhao   | female |   28 |    202 |  202 | 銷售         |
|  5 | liwenzhou | male   |   18 |    200 |  200 | 技術         |
+----+-----------+--------+------+--------+------+--------------+
5 rows in set (0.14 sec)
拿到了咱們想要的結果。

可是你看,咱們左表employee表中的dep_id爲204的那個數據沒有了,右表department表的id爲203的數據沒有了,由於咱們如今要的就是兩表能對應上的數據一塊兒查出來,那個204和203雙方對應不上。

#再看一個需求,我要查出技術部的員工的名字
mysql> select name from employee,department where employee.dep_id=department.id and department.name='技術';
ERROR 1052 (23000): Column 'name' in field list is ambiguous
#上面直接就報錯了,由於select後面直接寫的name,在兩個表合併起來的表中,是有兩個name字段的,直接寫name是不行的,要加上表名,再看:
mysql> select employee.name from employee,department where employee.dep_id=department.id and department.name='技術';
+-----------+
| name      |
+-----------+
| egon      |
| liwenzhou |
+-----------+
2 rows in set (0.09 sec)
結果就沒問題了
複製代碼

 

  可是你看上面的代碼有沒有什麼不太好的地方,雖然咱們可以完成咱們的事情,可是代碼可讀性很差,因此之後不要這麼寫,可是看圖:

    

    因此mysql爲咱們提供了一些專門作連表操做的方法,這些方法語義更加的明確,你一看就知道那些代碼是連表的,那些代碼是查詢的,其實上面的連表也是個查詢操做,可是咱們爲了區分明確,連表專門用連表的方法,查詢就專門用查詢的方法。那這些專門的方法都是什麼呢,看後面的內容:

  3 、外連接之左鏈接:優先顯示左表所有記錄

複製代碼
#以左表爲準,即找出全部員工信息,固然包括沒有部門的員工
#本質就是:在內鏈接的基礎上增長左邊有右邊沒有的結果  #注意語法:
mysql> select employee.id,employee.name,department.name as depart_name from employee left join department on employee.dep_id=department.id;
+----+------------+--------------+
| id | name       | depart_name  |
+----+------------+--------------+
|  1 | egon       | 技術         |
|  5 | liwenzhou  | 技術         |
|  2 | alex       | 人力資源     |
|  3 | wupeiqi    | 人力資源     |
|  4 | yuanhao    | 銷售         |
|  6 | jingliyang | NULL         |
+----+------------+--------------+
複製代碼

 

 

 

  4 、外連接之右鏈接:優先顯示右表所有記錄

複製代碼
#以右表爲準,即找出全部部門信息,包括沒有員工的部門
#本質就是:在內鏈接的基礎上增長右邊有左邊沒有的結果
mysql> select employee.id,employee.name,department.name as depart_name from employee right join department on employee.dep_id=department.id;
+------+-----------+--------------+
| id   | name      | depart_name  |
+------+-----------+--------------+
|    1 | egon      | 技術         |
|    2 | alex      | 人力資源     |
|    3 | wupeiqi   | 人力資源     |
|    4 | yuanhao   | 銷售         |
|    5 | liwenzhou | 技術         |
| NULL | NULL      | 運營         |
+------+-----------+--------------+
複製代碼

 

  5 、全外鏈接:顯示左右兩個表所有記錄

複製代碼
全外鏈接:在內鏈接的基礎上增長左邊有右邊沒有的和右邊有左邊沒有的結果
#注意:mysql不支持全外鏈接 full JOIN
#強調:mysql可使用此種方式間接實現全外鏈接
select * from employee left join department on employee.dep_id = department.id
union
select * from employee right join department on employee.dep_id = department.id
;
#查看結果
+------+------------+--------+------+--------+------+--------------+
| id   | name       | sex    | age  | dep_id | id   | name         |
+------+------------+--------+------+--------+------+--------------+
|    1 | egon       | male   |   18 |    200 |  200 | 技術         |
|    5 | liwenzhou  | male   |   18 |    200 |  200 | 技術         |
|    2 | alex       | female |   48 |    201 |  201 | 人力資源     |
|    3 | wupeiqi    | male   |   38 |    201 |  201 | 人力資源     |
|    4 | yuanhao    | female |   28 |    202 |  202 | 銷售         |
|    6 | jingliyang | female |   18 |    204 | NULL | NULL         |
| NULL | NULL       | NULL   | NULL |   NULL |  203 | 運營         |
+------+------------+--------+------+--------+------+--------------+

#注意 union與union all的區別:union會去掉相同的紀錄,由於union all是left join 和right join合併,因此有重複的記錄,經過union就將重複的記錄去重了。
複製代碼

 

三 符合條件鏈接查詢

複製代碼
#示例1:之內鏈接的方式查詢employee和department表,而且employee表中的age字段值必須大於25,即找出年齡大於25歲的員工以及員工所在的部門
select employee.name,department.name from employee inner join department
    on employee.dep_id = department.id
    where age > 25;

#示例2:之內鏈接的方式查詢employee和department表,而且以age字段的升序方式顯示
select employee.id,employee.name,employee.age,department.name from employee,department
    where employee.dep_id = department.id
    and age > 25
    order by age asc;
複製代碼

 

四 子查詢

  子查詢其實就是將你的一個查詢結果用括號括起來,這個結果也是一張表,就能夠將它交給另一個sql語句,做爲它的一個查詢依據來進行操做。

  來,咱們簡單來個需求:技術部都有哪些員工的姓名,都顯示出來: 一、看一下和哪一個表有關,而後from找到兩個表  二、進行一個連表操做 三、基於連表的結果來一個過濾就能夠了

複製代碼
#咱們以前的作法是:先連表
mysql> select * from employee inner join department on employee.dep_id = department.id; 
+----+-----------+--------+------+--------+------+--------------+
| id | name      | sex    | age  | dep_id | id   | name         |
+----+-----------+--------+------+--------+------+--------------+
|  1 | egon      | male   |   18 |    200 |  200 | 技術         |
|  2 | alex      | female |   48 |    201 |  201 | 人力資源     |
|  3 | wupeiqi   | male   |   38 |    201 |  201 | 人力資源     |
|  4 | yuanhao   | female |   28 |    202 |  202 | 銷售         |
|  5 | liwenzhou | male   |   18 |    200 |  200 | 技術         |
+----+-----------+--------+------+--------+------+--------------+
5 rows in set (0.10 sec)

#而後根據連表的結果進行where過濾,將select*改成select employee.name

mysql> select employee.name from employee inner join department on employee.dep_id = department.id where department.name='技術';

  +-----------+
  | name |
  +-----------+
  | egon |
  | liwenzhou |
  +-----------+
  2 rows in set (0.09 sec)

複製代碼

 

  而後看一會兒查詢這種方式的寫法:它的作法就是解決完一個問題,再解決下一個問題,針對咱們上面的需求,你想,咱們的需求是否是說找技術部門下面有哪些員工對不對,若是你直接找員工表,你能肯定哪一個dep_id的數值表示的是技術部門嗎,不能,因此我們是否是應該先肯定一個技術部門對應的id號是多少,而後根據部門的id號,再去員工表裏面查詢一下dep_id爲技術部門對應的部門表的那個id號的全部的員工表裏面的記錄:好,那咱們看一下下面的操做

複製代碼
#首先從部門表裏面找到技術部門對應的id
mysql> select id from department where name='技術';
+------+
| id   |
+------+
|  200 |
+------+
1 row in set (0.00 sec)

#那咱們把上面的查詢結果用括號括起來,它就表示一條id=200的數據,而後咱們經過員工表來查詢dep_id=這條數據做爲條件來查詢員工的name
mysql> select name from employee where dep_id = (select id from department where name='技術');
+-----------+
| name      |
+-----------+
| egon      |
| liwenzhou |
+-----------+
2 rows in set (0.00 sec)
上面這些就是子查詢的一個思路,解決一個問題,再解決另一個問題,你子查詢裏面可不能夠是多個表的查詢結果,固然能夠,而後再經過這個結果做爲依據來進行過濾,而後咱們學一會兒查詢裏面其餘的內容,往下學。
複製代碼

 

子查詢:
#1:子查詢是將一個查詢語句嵌套在另外一個查詢語句中。 #2:內層查詢語句的查詢結果,能夠爲外層查詢語句提供查詢條件。 #3:子查詢中能夠包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等關鍵字 #4:還能夠包含比較運算符:= 、 !=、> 、<等

  一、帶IN關鍵字的子查詢

複製代碼
#查詢員工平均年齡在25歲以上的部門名,能夠用連表,也能夠用子查詢,咱們用子查詢來搞一下
select id,name from department
    where id in 
        (select dep_id from employee group by dep_id having avg(age) > 25);
#連表來搞一下上面這個需求
select department.name from department inner join employee on department.id=employee.dep_id 
    group by department.name 
    having avg(age)>25;
總結:子查詢的思路和解決問題同樣,先解決一個而後拿着這個的結果再去解決另一個問題,連表的思路是先將兩個表關聯在一塊兒,而後在進行group by啊過濾啊等等操做,二者的思路是不同的

#查看技術部員工姓名
select name from employee
    where dep_id in 
        (select id from department where name='技術');

#查看不足1人的部門名(子查詢獲得的是有人的部門id)
select name from department where id not in (select distinct dep_id from employee);
複製代碼

 

  二、帶比較運算符的子查詢

複製代碼
#比較運算符:=、!=、>、>=、<、<=、<>
#查詢大於全部人平均年齡的員工名與年齡
mysql> select name,age from emp where age > (select avg(age) from emp);
+---------+------+
| name | age |
+---------+------+
| alex | 48 |
| wupeiqi | 38 |
+---------+------+
2 rows in set (0.00 sec)


#查詢大於部門內平均年齡的員工名、年齡
select t1.name,t1.age from emp t1
inner join 
(select dep_id,avg(age) avg_age from emp group by dep_id) t2
on t1.dep_id = t2.dep_id
where t1.age > t2.avg_age;
複製代碼

  

  三、帶EXISTS關鍵字的子查詢

    EXISTS關字鍵字表示存在。在使用EXISTS關鍵字時,內層查詢語句不返回查詢的記錄。而是返回一個真假值。True或False
    當返回True時,外層查詢語句將進行查詢;當返回值爲False時,外層查詢語句不進行查詢。還能夠寫not exists,和exists的效果就是反的

    

複製代碼
#department表中存在dept_id=203,Ture
mysql> select * from employee
    ->     where exists  
    ->         (select id from department where id=200); 
+----+------------+--------+------+--------+
| id | name       | sex    | age  | dep_id |
+----+------------+--------+------+--------+
|  1 | egon       | male   |   18 |    200 |
|  2 | alex       | female |   48 |    201 |
|  3 | wupeiqi    | male   |   38 |    201 |
|  4 | yuanhao    | female |   28 |    202 |
|  5 | liwenzhou  | male   |   18 |    200 |
|  6 | jingliyang | female |   18 |    204 |
+----+------------+--------+------+--------+

#department表中存在dept_id=205,False
mysql> select * from employee
    ->     where exists
    ->         (select id from department where id=204);
Empty set (0.00 sec)
複製代碼

 

 

  練習:經過連表的方式來查詢每一個部門最新入職的那位員工

複製代碼
company.employee
    員工id      id                  int             
    姓名        emp_name            varchar
    性別        sex                 enum
    年齡        age                 int
    入職日期     hire_date           date
    崗位        post                varchar
    職位描述     post_comment        varchar
    薪水        salary              double
    辦公室       office              int
    部門編號     depart_id           int



#建立表,只須要建立這一張表
create table employee(
id int not null unique auto_increment,
name varchar(20) not null,
sex enum('male','female') not null default 'male', #大部分是男的
age int(3) unsigned not null default 28,
hire_date date not null,
post varchar(50),
post_comment varchar(100),
salary double(15,2),
office int, #一個部門一個屋子
depart_id int
);


#查看錶結構
mysql> desc employee;
+--------------+-----------------------+------+-----+---------+----------------+
| Field        | Type                  | Null | Key | Default | Extra          |
+--------------+-----------------------+------+-----+---------+----------------+
| id           | int(11)               | NO   | PRI | NULL    | auto_increment |
| name         | varchar(20)           | NO   |     | NULL    |                |
| sex          | enum('male','female') | NO   |     | male    |                |
| age          | int(3) unsigned       | NO   |     | 28      |                |
| hire_date    | date                  | NO   |     | NULL    |                |
| post         | varchar(50)           | YES  |     | NULL    |                |
| post_comment | varchar(100)          | YES  |     | NULL    |                |
| salary       | double(15,2)          | YES  |     | NULL    |                |
| office       | int(11)               | YES  |     | NULL    |                |
| depart_id    | int(11)               | YES  |     | NULL    |                |
+--------------+-----------------------+------+-----+---------+----------------+

#插入記錄
#三個部門:教學,銷售,運營
insert into employee(name,sex,age,hire_date,post,salary,office,depart_id) values
('egon','male',18,'20170301','老男孩駐沙河辦事處外交大使',7300.33,401,1), #如下是教學部
('alex','male',78,'20150302','teacher',1000000.31,401,1),
('wupeiqi','male',81,'20130305','teacher',8300,401,1),
('yuanhao','male',73,'20140701','teacher',3500,401,1),
('liwenzhou','male',28,'20121101','teacher',2100,401,1),
('jingliyang','female',18,'20110211','teacher',9000,401,1),
('jinxin','male',18,'19000301','teacher',30000,401,1),
('成龍','male',48,'20101111','teacher',10000,401,1),

('歪歪','female',48,'20150311','sale',3000.13,402,2),#如下是銷售部門
('丫丫','female',38,'20101101','sale',2000.35,402,2),
('丁丁','female',18,'20110312','sale',1000.37,402,2),
('星星','female',18,'20160513','sale',3000.29,402,2),
('格格','female',28,'20170127','sale',4000.33,402,2),

('張野','male',28,'20160311','operation',10000.13,403,3), #如下是運營部門
('程咬金','male',18,'19970312','operation',20000,403,3),
('程咬銀','female',18,'20130311','operation',19000,403,3),
('程咬銅','male',18,'20150411','operation',18000,403,3),
('程咬鐵','female',18,'20140512','operation',17000,403,3)
;

#ps:若是在windows系統中,插入中文字符,select的結果爲空白,能夠將全部字符編碼統一設置成gbk
複製代碼

 

  答案:

複製代碼
SELECT
    *
FROM
    emp AS t1
INNER JOIN (   #和虛擬表進行連表
    SELECT
        post,
        max(hire_date) as max_date  #給這個最大的日期取個別名叫作max_date,先將每一個部門最近入職的最大的日期的信息篩選出來,經過這個表來和咱們上面的總表進行關聯
    FROM
        emp
    GROUP BY
        post
) AS t2 ON t1.post = t2.post  #給虛擬表取個別名叫作t2
WHERE
    t1.hire_date = t2.max_date;  #而後再經過where來過濾出,入職日期和最大日期相等的記錄,就是咱們要的內容
複製代碼

 

五 綜合練習 

  表結構爲

 

  

複製代碼
#建立表及插入記錄
CREATE TABLE class (
  cid int(11) NOT NULL AUTO_INCREMENT,
  caption varchar(32) NOT NULL,
  PRIMARY KEY (cid)
) ENGINE=InnoDB CHARSET=utf8;

INSERT INTO class VALUES
(1, '三年二班'), 
(2, '三年三班'), 
(3, '一年二班'), 
(4, '二年九班');

CREATE TABLE course(
  cid int(11) NOT NULL AUTO_INCREMENT,
  cname varchar(32) NOT NULL,
  teacher_id int(11) NOT NULL,
  PRIMARY KEY (cid),
  KEY fk_course_teacher (teacher_id),
  CONSTRAINT fk_course_teacher FOREIGN KEY (teacher_id) REFERENCES teacher (tid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO course VALUES
(1, '生物', 1), 
(2, '物理', 2), 
(3, '體育', 3), 
(4, '美術', 2);

CREATE TABLE score (
  sid int(11) NOT NULL AUTO_INCREMENT,
  student_id int(11) NOT NULL,
  course_id int(11) NOT NULL,
  num int(11) NOT NULL,
  PRIMARY KEY (sid),
  KEY fk_score_student (student_id),
  KEY fk_score_course (course_id),
  CONSTRAINT fk_score_course FOREIGN KEY (course_id) REFERENCES course (cid),
  CONSTRAINT fk_score_student FOREIGN KEY (student_id) REFERENCES student(sid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO score VALUES
(1, 1, 1, 10),
(2, 1, 2, 9),
(5, 1, 4, 66),
(6, 2, 1, 8),
(8, 2, 3, 68),
(9, 2, 4, 99),
(10, 3, 1, 77),
(11, 3, 2, 66),
(12, 3, 3, 87),
(13, 3, 4, 99),
(14, 4, 1, 79),
(15, 4, 2, 11),
(16, 4, 3, 67),
(17, 4, 4, 100),
(18, 5, 1, 79),
(19, 5, 2, 11),
(20, 5, 3, 67),
(21, 5, 4, 100),
(22, 6, 1, 9),
(23, 6, 2, 100),
(24, 6, 3, 67),
(25, 6, 4, 100),
(26, 7, 1, 9),
(27, 7, 2, 100),
(28, 7, 3, 67),
(29, 7, 4, 88),
(30, 8, 1, 9),
(31, 8, 2, 100),
(32, 8, 3, 67),
(33, 8, 4, 88),
(34, 9, 1, 91),
(35, 9, 2, 88),
(36, 9, 3, 67),
(37, 9, 4, 22),
(38, 10, 1, 90),
(39, 10, 2, 77),
(40, 10, 3, 43),
(41, 10, 4, 87),
(42, 11, 1, 90),
(43, 11, 2, 77),
(44, 11, 3, 43),
(45, 11, 4, 87),
(46, 12, 1, 90),
(47, 12, 2, 77),
(48, 12, 3, 43),
(49, 12, 4, 87),
(52, 13, 3, 87);


CREATE TABLE student(
  sid int(11) NOT NULL AUTO_INCREMENT,
  gender char(1) NOT NULL,
  class_id int(11) NOT NULL,
  sname varchar(32) NOT NULL,
  PRIMARY KEY (sid),
  KEY fk_class (class_id),
  CONSTRAINT fk_class FOREIGN KEY (class_id) REFERENCES class (cid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO student VALUES
(1, '男', 1, '理解'), 
(2, '女', 1, '鋼蛋'), 
(3, '男', 1, '張三'), 
(4, '男', 1, '張一'), 
(5, '女', 1, '張二'), 
(6, '男', 1, '張四'), 
(7, '女', 2, '鐵錘'), 
(8, '男', 2, '李三'), 
(9, '男', 2, '李一'), 
(10, '女', 2, '李二'), 
(11, '男', 2, '李四'), 
(12, '女', 3, '如花'), 
(13, '男', 3, '劉三'), 
(14, '男', 3, '劉一'), 
(15, '女', 3, '劉二'), 
(16, '男', 3, '劉四');

CREATE TABLE teacher(
  tid int(11) NOT NULL AUTO_INCREMENT,
  tname varchar(32) NOT NULL,
  PRIMARY KEY (tid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO teacher VALUES
(1, '張磊老師'), 
(2, '李平老師'), 
(3, '劉海燕老師'), 
(4, '朱雲海老師'), 
(5, '李傑老師');
複製代碼

 

 

!!!重中之重:練習以前務必搞清楚sql邏輯查詢語句的執行順序

連接:https://www.cnblogs.com/clschao/articles/9995517.html

 

  練習題目

 

參考答案:https://www.cnblogs.com/clschao/articles/9995776.html

相關文章
相關標籤/搜索