1. 程式人生 > >表(修改、排序、分頁、表關聯)

表(修改、排序、分頁、表關聯)

where子句(條件查詢):按照條件表示式指定的條件進行查詢。

group by子句(分組):按照屬性名指定的欄位進行分組。group by子句通常和count()sum()等聚合函式一起使用。

having子句(篩選):有group by才能having子句,只有滿足條件表示式中指定的條件的才能夠輸出。

order by子句(排序):按照屬性名指定的欄位進行排序。排序方式由“asc”“desc”兩個引數指出,預設是按照“asc”來排序,即升序。

limit(限制結果集)。

 

 

 

 

mysql中五種常用的聚合函式:

1max(列名):求最大值。

2min(列名):求最小值。

2sum(列名):求和。

4avg(列名):求平均值。

5count(列名):統計記錄的條數。

 

 

為了方便檢視資料,可以對資料進行排序

語法:order by 欄位 asc 或者 desc

說明   按照某欄位正序,倒序使用desc

將行資料按照列1進行排序,如果某些行列1的值相同時,則按照列2排序,以此類推

預設按照列值從小到大排列(asc

asc從小到大排列,即升序

desc從大到小排序,即降序

1:查詢學生資訊,按學號降序

select * from student order by id desc  

2:查詢學生資訊,按名稱升序

select * from student order by name asc

3:顯示所有的學生資訊,先按照年齡從大-->小排序,當年齡相同時 按照身高從高-->矮排序

select * from student order by age desc,height desc

 

 

聚合函式

 

 

 

1count函式

 

count(*):返回表中滿足

where條件的行的數量

 

mysql> select count(*) from salary_tab where salary='1000';

+----------+

| count(*) |

+----------+

|        2 |

+----------+

 

mysql> select count(*) from salary_tab;  #沒有條件,預設統計表資料行數

+----------+

| count(*) |

+----------+

|        5 |

+----------+

count():返回列值非空的行的數量

 

mysql> select count(salary) from salary_tab;

+---------------+

| count(salary) |

+---------------+

|             4 |

+---------------+

count(distinct ):返回列值非空的、並且列值不重複的行的數量

 

mysql> select count(distinct salary) from salary_tab;

+------------------------+

| count(distinct salary) |

+------------------------+

|                      3 |

+------------------------+

count(expr):根據表示式統計資料

 

mysql> select * from TT;

+------+------------+

| UNIT | DATE       |

+------+------------+

| a    | 2018-04-03 |

| a    | 2017-12-12 |

| b    | 2018-01-01 |

| b    | 2018-04-03 |

| c    | 2016-06-06 |

| d    | 2018-03-03 |

+------+------------+

6 rows in set (0.00 sec)

 

mysql> select UNIT as '單位',

    ->     COUNT(TO_DAYS(DATE)=TO_DAYS(NOW()) or null) as '今日統計',

    ->     COUNT(YEAR(DATE)=YEAR(NOW()) or null) as '今年統計'

    -> from v_jjd

    -> group by JJDW;

+------+----------+----------+

| 單位  | 今日統計  | 今年統計  |

+------+----------+----------+

| a    |        1 |        1 |

| b    |        1 |        2 |

| c    |        0 |        0 |

| d    |        0 |        1 |

+------+----------+----------+

4 rows in set (0.00 sec)

 

 

2maxmin函式---統計列中的最大最小值

 

mysql> select max(salary) from salary_tab;

+-------------+

| max(salary) |

+-------------+

|     3000.00 |

+-------------+

 

mysql> select min(salary) from salary_tab;

+-------------+

| min(salary) |

+-------------+

|     1000.00 |

+-------------+

注意:如果統計的列中只有NULL值,那麼MAXMIN就返回NULL

 

 

 

3sumavg函式---求和與求平均

 

!!表中列值為null的行不參與計算

 

mysql> select sum(salary) from salary_tab;

+-------------+

| sum(salary) |

+-------------+

|     7000.00 |

+-------------+

 

mysql> select avg(salary) from salary_tab;

+-------------+

| avg(salary) |

+-------------+

| 1750.000000 |

+-------------+

 

mysql> select avg(ifnull(salary,0)) from salary_tab;

+-----------------------+

| avg(ifnull(salary,0)) |

+-----------------------+

|           1400.000000 |

+-----------------------+

注意:要想列值為NULL的行也參與組函式的計算,必須使用IFNULL函式對NULL值做轉換。

 

 

 

 

 

二、分組SELECT

 

SELECT select_expr [, select_expr ...]

 

    [FROM table_references

 

      [PARTITION partition_list]

 

    [WHERE where_condition]

 

    [GROUP BY {col_name | expr | position}

 

      [ASC | DESC], ... [WITH ROLLUP]]

 

    [HAVING where_condition]

 

    [ORDER BY {col_name | expr | position}

 

      [ASC | DESC], ...]

 

[LIMIT {[offset,] row_count | row_count OFFSET offset}]

分組SELECT的基本格式:

 

  select [聚合函式] 欄位名 from 表名

 

    [where 查詢條件]

 

    [group by 欄位名]

 

    [having 過濾條件]

 

1group by子句

 

  根據給定列或者表示式的每一個不同的值將表中的行分成不同的組,使用組函式返回每一組的統計資訊

 

規則:

 

  ①出現在SELECT子句中的單獨的列,必須出現在GROUP BY子句中作為分組列

 

  ②分組列可以不出現在SELECT子句中

 

  ③分組列可出現在SELECT子句中的一個複合表示式中

 

  ④如果GROUP BY後面是一個複合表示式,那麼在SELECT子句中,它必須整體作為一個表示式的一部分才能使用。

 

1)指定一個列進行分組

 

mysql> select salary,count(*) from salary_tab

    -> where salary>=2000

    -> group by salary;   

+---------+----------+

| salary  | count(*) |

+---------+----------+

| 2000.00 |        1 |

| 3000.00 |        1 |

+---------+----------+

2)指定多個分組列,‘大組中再分小組’

 

mysql> select userid,count(salary) from salary_tab

    -> where salary>=2000

    -> group by salary,userid;   

+--------+---------------+

| userid | count(salary) |

+--------+---------------+

|      2 |             1 |

|      3 |             1 |

+--------+---------------+

3)根據表示式分組

 

mysql> select year(payment_date),count(*)

    -> from PENALTIES

    -> group by year(payment_date);

+--------------------+----------+

| year(payment_date) | count(*) |

+--------------------+----------+

|               1980 |        3 |

|               1981 |        1 |

|               1982 |        1 |

|               1983 |        1 |

|               1984 |        2 |

+--------------------+----------+

5 rows in set (0.00 sec)

4)帶有排序的分組:如果分組列和排序列相同,則可以合併group byorder by子句

 

mysql> select teamno,count(*)

    -> from MATCHES

    -> group by teamno

    -> order by teamno desc;

+--------+----------+

| teamno | count(*) |

+--------+----------+

|      2 |        5 |

|      1 |        8 |

+--------+----------+

2 rows in set (0.00 sec)

 

mysql> select teamno,count(*)

    -> from MATCHES

    -> group by teamno desc;  #可以把desc(或者asc)包含到group by子句中簡化

+--------+----------+

| teamno | count(*) |

+--------+----------+

|      2 |        5 |

|      1 |        8 |

+--------+----------+

2 rows in set (0.00 sec)

對於分組聚合注意:

 

  通過select在返回集欄位中,這些欄位要麼就要包含在group by語句後面,作為分組的依據,要麼就要被包含在聚合函式中。我們可以將group by操作想象成如下的一個過程:首先系統根據select語句得到一個結果集,然後根據分組欄位,將具有相同分組欄位的記錄歸併成了一條記錄。這個時候剩下的那些不存在與group by語句後面作為分組依據的欄位就很有可能出現多個值,但是目前一種分組情況只有一條記錄,一個數據格是無法放入多個數值的,所以這個時候就需要通過一定的處理將這些多值的列轉化成單值,然後將其放在對應的資料格中,那麼完成這個步驟的就是前面講到的聚合函式,這也就是為什麼這些函式叫聚合函數了。

 

 

 

2GROUP_CONCAT()函式

 

  函式的值等於屬於一個組的指定列的所有值,以逗號隔開,並且以字串表示。

 

1:對於每個球隊,得到其編號和所有球員的編號

 

mysql> select teamno,group_concat(playerno)

    -> from MATCHES

    -> group by teamno;

+--------+------------------------+

| teamno | group_concat(playerno) |

+--------+------------------------+

|      1 | 6,6,6,44,83,2,57,8     |

|      2 | 27,104,112,112,8       |

+--------+------------------------+

2 rows in set (0.01 sec)

如果沒有group by子句,group_concat返回一列的所有值

 

2:得到所有的罰款編號列表

 

mysql> select group_concat(paymentno)

    -> from PENALTIES;

+-------------------------+

| group_concat(paymentno) |

+-------------------------+

| 1,2,3,4,5,6,7,8         |

+-------------------------+

1 row in set (0.00 sec)

 

 

3with rollup子句:用來要求在一條group by子句中進行多個不同的分組

 

用的比較少點,但是有時可以根據具體的需求使用

 

  如果有子句GROUP BY E1,E2,E3,E4 WITH ROLLUP

 

  那麼將分別執行以下分組:[E1,E2,E3,E4][E1,E2,E3][E1,E2][E1][]

 

注意:[ ]表示所有行都分在一組中

 

示例:按照球員的性別和居住城市,統計球員的總數;統計每個性別球員的總數;統計所有球員的總數

 

mysql> select sex,town,count(*)

    -> from PLAYERS

    -> group by sex,town with rollup;

+-----+-----------+----------+

| sex | town      | count(*) |

+-----+-----------+----------+

| F   | Eltham    |        2 |

| F   | Inglewood |        1 |

| F   | Midhurst  |        1 |

| F   | Plymouth  |        1 |

| F   | NULL      |        5 |

| M   | Douglas   |        1 |

| M   | Inglewood |        1 |

| M   | Stratford |        7 |

| M   | NULL      |        9 |

| NULL | NULL      |       14 |

+-----+-----------+----------+

10 rows in set (0.00 sec)

 

 

4HAVING子句:對分組結果進行過濾

 

注意:

 

  不能使用WHERE子句對分組後的結果進行過濾

 

  不能在WHERE子句中使用組函式,僅用於過濾行

 

mysql> select playerno

    -> from PENALTIES

    -> where count(*)>1

    -> group by playerno;

ERROR 1111 (HY000): Invalid use of group function

因為WHERE子句比GROUP BY先執行,而組函式必須在分完組之後才執行,且分完組後必須使用having子句進行結果集的過濾。

 

基本語法:

 

SELECT   select_expr [, select_expr ...]

 

   FROM  table_name

 

   [WHERE where_condition]

 

   [GROUP BY {col_name | expr} [ASC | DESC], ... [WITH ROLLUP]]

 

[HAVING where_condition]

!!!having子語句與where子語句區別:

 

  where子句在分組前對記錄進行過濾;

 

  having子句在分組後對記錄進行過濾

 

mysql> select salary,count(*) from salary_tab

    -> where salary>=2000

    -> group by salary

    -> having count(*)>=0;

+---------+----------+

| salary  | count(*) |

+---------+----------+

| 2000.00 |        1 |

| 3000.00 |        1 |

+---------+----------+

1HAVING可以單獨使用而不和GROUP BY配合,如果只有HAVING子句而沒有GROUP BY,表中所有的行分為一組

 

2HAVING子句中可以使用組函式

 

3HAVING子句中的列,要麼出現在一個組函式中,要麼出現在GROUP BY子句中(否則出錯)

 

mysql> select town,count(*)

    -> from PLAYERS

    -> group by town

    -> having birth_date>'1970-01-01';

ERROR 1054 (42S22): Unknown column 'birth_date' in 'having clause'

mysql> select town,count(*)

    -> from PLAYERS

    -> group by town

    -> having town in ('Eltham','Midhurst');

+----------+----------+

| town     | count(*) |

+----------+----------+

| Eltham   |        2 |

| Midhurst |        1 |

+----------+----------+

2 rows in set (0.00 sec)

 

 

limit 分段取值

 

語法 limi m,n

 

m為其實位置,n為取幾個

 

select * from student limit 0,2

 

從第一個開始取,取兩個,如果不寫第一個引數,就是預設從第一個引數取值,取n個

 

select * from student limit 2

 

 

連線查詢(join 語法)

 

join 用於多表中欄位之間的聯絡,語法如下:

... FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona

table1:左表;table2:右表。

JOIN 按照功能大致分為如下三類:

INNER JOIN(內連線,或等值連線):取得兩個表中存在連線匹配關係的記錄。

LEFT JOIN(左連線):取得左表(table1)完全記錄,即是右表(table2)並無對應匹配記錄。

RIGHT JOIN(右連線):與 LEFT JOIN 相反,取得右表(table2)完全記錄,即是左表(table1)並無匹配對應記錄。

注意:mysql不支援Full join,不過可以通過UNION 關鍵字來合併 LEFT JOIN RIGHT JOIN來模擬FULL join.

接下來給出一個列子用於解釋下面幾種分類。如下兩個表(A,B)

  1. mysql> select A.id,A.name,B.name from A,B where A.id=B.id;
  2. +----+-----------+-------------+
  3. | id | name       | name             |
  4. +----+-----------+-------------+
  5. |  1 | Pirate       | Rutabaga      |
  6. |  2 | Monkey    | Pirate            |
  7. |  3 | Ninja         | Darth Vader |
  8. |  4 | Spaghetti  | Ninja             |
  9. +----+-----------+-------------+
  10. 4 rows in set (0.00 sec)

.Inner join

內連線,也叫等值連線,inner join產生同時符合AB的一組資料。

  1. mysql> select * from A inner join B on A.name = B.name;
  2. +----+--------+----+--------+
  3. | id | name   | id | name   |
  4. +----+--------+----+--------+
  5. |  1 | Pirate |  2 | Pirate |
  6. |  3 | Ninja  |  4 | Ninja  |
  7. +----+--------+----+--------+

 

.Left join

  1. mysql> select * from A left join B on A.name = B.name;
  2. #或者:select * from A left outer join B on A.name = B.name;
  3. +----+-----------+------+--------+
  4. | id | name      | id   | name   |
  5. +----+-----------+------+--------+
  6. |  1 | Pirate    |    2 | Pirate |
  7. |  2 | Monkey    | NULL | NULL   |
  8. |  3 | Ninja     |    4 | Ninja  |
  9. |  4 | Spaghetti | NULL | NULL   |
  10. +----+-----------+------+--------+
  11. 4 rows in set (0.00 sec)

left join,(或left outer join:Mysql中兩者等價,推薦使用left join.)左連線從左表(A)產生一套完整的記錄,與匹配的記錄(右表(B)) .如果沒有匹配,右側將包含null

 

如果想只從左表(A)中產生一套記錄,但不包含右表(B)的記錄,可以通過設定where語句來執行,如下:

  1. mysql> select * from A left join B on A.name=B.name where A.id is null or B.id is null;
  2. +----+-----------+------+------+
  3. | id | name      | id   | name |
  4. +----+-----------+------+------+
  5. |  2 | Monkey    | NULL | NULL |
  6. |  4 | Spaghetti | NULL | NULL |
  7. +----+-----------+------+------+
  8. 2 rows in set (0.00 sec)

 

同理,還可以模擬inner join. 如下:

  1. mysql> select * from A left join B on A.name=B.name where A.id is not null and B.id is not null;
  2. +----+--------+------+--------+
  3. | id | name   | id   | name   |
  4. +----+--------+------+--------+
  5. |  1 | Pirate |    2 | Pirate |
  6. |  3 | Ninja  |    4 | Ninja  |
  7. +----+--------+------+--------+
  8. 2 rows in set (0.00 sec)

求差集:

根據上面的例子可以求差集,如下:

  1. SELECT * FROM A LEFT JOIN B ON A.name = B.name
  2. WHERE B.id IS NULL
  3. union
  4. SELECT * FROM A right JOIN B ON A.name = B.name
  5. WHERE A.id IS NULL;
  6. # 結果
  7. +------+-----------+------+-------------+
  8. | id   | name      | id   | name        |
  9. +------+-----------+------+-------------+
  10. |    2 | Monkey    | NULL | NULL        |
  11. |    4 | Spaghetti | NULL | NULL        |
  12. | NULL | NULL      |    1 | Rutabaga    |
  13. | NULL | NULL      |    3 | Darth Vader |
  14. +------+-----------+------+-------------+

 

.Right join

  1. mysql> select * from A right join B on A.name = B.name;
  2. +------+--------+----+-------------+
  3. | id   | name   | id | name        |
  4. +------+--------+----+-------------+
  5. | NULL | NULL   |  1 | Rutabaga    |
  6. |    1 | Pirate |  2 | Pirate      |
  7. | NULL | NULL   |  3 | Darth Vader |
  8. |    3 | Ninja  |  4 | Ninja       |
  9. +------+--------+----+-------------+
  10. 4 rows in set (0.00 sec)

left join

 

 

Mysql建表思路理解

 

一對一   one on one

 

一張表的一條記錄一定只能與另外一張表的一條記錄進行對應,反之亦然。  學生表:姓名,性別,年齡,身高,體重,籍貫,家庭住址,緊急聯絡人 其中姓名、性別、年齡、身高,體重屬於常用資料,但是籍貫、住址和聯絡人為不常用資料 如果每次查詢都是查詢所有資料,不常用的資料就會影響效率,實際又不用 常用資訊表:ID(P),姓名,性別,年齡,身高,體重 不常用資訊表:ID(P),籍貫,家庭住址,緊急聯絡人  解決方案:將常用的和不常用的資訊分享儲存,分成兩張表 不常用資訊表和常用資訊表,保證不常用資訊表與常用資訊表能夠對應上:找一個具有唯一性的 欄位來共同連線兩張表。 一個常用表中的一條記錄永遠只能在一張不常用表中匹配一條記錄,反之亦然。

 

 

 

一對多  one on many

 

 

一張表中有一條記錄可以對應另外一張表中的多條記錄;但是反過來,另外一張表的一條記錄 只能對應第一張表的一條記錄,這種關係就是一對多或多對一 母親與孩子的關係:母親,孩子兩個實體 母親表:ID(P),名字,年齡,性別 孩子表:ID(P),名字,年齡,性別 以上關係:一個媽媽可以在孩子表中找到多條記錄(也可能是一條),但是一個孩子只能找到一個媽媽 是一種典型的一對多的關係。 但是以上設計:解決了實體的設計表問題,但是沒有解決關係問題,孩子找不到母親,母親也找不到孩子  解決方案:在某一張表中增加一個欄位,能夠找到另外一張表中的記錄:在孩子表中增加一個欄位 指向母親表,因為孩子表的記錄只能匹配到一條母親表的記錄。 母親表:ID(P),名字,年齡,性別 孩子表:ID(P),名字,年齡,性別,母親表ID(母親表主鍵)

 

 

 

 

 

 

多對多 many on many

 

一對錶中(A)的一條記錄能夠對應另外一張表(B)中的多條記錄;同時B表中的一條記錄 也能對應A表中的多條記錄  老師和學生 老師表 T_ID(P),姓名,性別 學生表 S_ID(P),姓名,性別 以上設計方案:實現了實體的設計,但是沒有維護實體的關係 一個老師教過多個學生,一個學生也被多個老師教過  解決方案:增加一張中間關係表 老師與學生的關係表:ID(P),T_ID,S_ID  老師表與中間表形成一對多的關係,而中間表是多表;維護了能夠唯一找到一表的關係; 同樣的學生表與中間表也是一個一對多的關係;  學生找老師:找出學生ID--->中間表尋找匹配記錄(多條)--->老師表匹配(一條) 老師找學生:找出老師ID--->中間表尋找匹配記錄(多條)--->學生表匹配(一條)