1. 程式人生 > 資料庫 >資料庫中select 查詢詳解

資料庫中select 查詢詳解

未整理

轉載:

 

資料查詢操作介紹

在資料庫操作中,使用頻率最多的是查詢操作。

查詢資料時,根據不同的需求,條件對資料庫中的資料進行查詢 ,並返回結果

單表查詢資料

查詢資料庫使用 select 命令。 這個命令相對比較複雜。可變化樣式較多,這裡分功能依次講解。

  1. 查詢資料表中所有資料 語法:select * from 表名

     select * from t_student;
    

  2. 查詢指定欄位的顯示 語法:select 欄位1,欄位2,... from 表名

     select c_id,c_name,c_address from t_student;
    

  3. as 別名 在查詢時,預設結果顯示的欄位和表中欄位名相同,可以通過別名來修改顯示的樣式 語法:select 欄位1 as 別名,欄位2 別名,... from 表名

     select c_id as 學號 ,c_name as 姓名 ,c_address 地址 from t_student;
    

     

    在給欄位起別名時,可以使用 as ,也可以直接在欄位後跟別名,省略 as 。

  4. 消除重複資料 在查詢資料時,查詢結果可能會有很多重複的資料,如果不想重複,可以使用 distinct 來實現去重。 語法:select distinct 欄位名 from 表名

     select distinct c_address from t_student;
    

    注意:distinct 在去重時,會比較所有的指定欄位,只有完全相同時才認為是重複的。

  5. 帶條件查詢 where 子句 查詢資料時,需要根據不同的需求設定條件。 通過 where 子句來設定查詢條件

     select * from t_student where c_gender='男';
    

     

  1. 比較運算子

    • 等於: =
    • 大於: >
    • 大於等於: >=
    • 小於: <
    • 小於等於: <=
    • 不等於: != 或 <>

      select * from t_student where c_age < 20;
      

  2. 邏輯運算子

    • and
    • or
    • not
      select * from t_student where c_age < 20 and c_gender = '女';
      
  3. 模糊查詢

    • like
    • % 表示任意多個任意字元
    • _ 表示一個任意字元

      1.   select * from t_student where c_name like '孫';
      2.   select * from t_student where c_name like '孫%';
      3.   select * from t_student where c_name like '孫_';

  4. 範圍查詢

    • in 表示在一個非連續的範圍內 , 可以使用 or 實現
      select * from t_students where id in(1,3,8);
      
    • between ... and ... 表示在一個連續的範圍內,可以使用 and 實現 ``` 
  5. 空判斷 在資料庫中,允許在d資料新增是沒有資料,使用空值來表示。 空值不等於0,也不等於‘’,需要使用特殊的判斷方式

    • 判斷空值
      語法:is null

      select * from t_student where c_age is null;
      

    • 判斷非空值 語法:is not null

      select * from t_student where c_age is not null;
      

  6. 查詢結果排序 排序是一個在查詢資料時非常重要的操作。比如買東西時,想按一定的條件進行有序顯示。就需要使用排序

    排序使用 order by 子句 asc(預設) 升序 / desc 降序 語法:select * from 表名 order by 列1 asc|desc [,列2 asc|desc,...]

    • 單欄位排序

      1.   select * from t_student order by c_age;
      2.   select * from t_student order by c_age asc;

      預設使用就是升序排序,可以不指定 asc ,效果相同。

    • 多欄位排序 可以對多個欄位進行排序,只需將欄位的排序方式依次寫在 order by 後面即可,欄位間使用逗號分隔

      select * from t_student order by c_age desc,c_id asc;
      

  7. 分頁查詢查詢資料庫時,由於資料較多,在顯示過程中不可能將資料全部顯示。 可以使用分頁查詢,只顯示指定的一部分資料 語法:select from 表名 limit start=0,count *說明

    • 從start開始,獲取count條資料
    • start預設值為0
    • 需要獲取資料的前n條的時候可以直接寫 limit n

      1.   select * from t_student limit 3;
      2.   select * from t_student limit 2,3;

      查詢第 N 頁 M 條資料,可以通過公式算出:(N - 1) * M

  8. 聚合函式在MySQL中提供了一些定義好的函式,利用這些函式提供對資料的統計功能。 常用的聚合函式如圖: 

    • sum 求和函式 對指定的欄位求和

      select sum(c_age) from t_student;
      

    • avg 求平均值函式 對指定欄位求平均值

      select avg(c_age) from t_student;
      

    • max 求最大值函式

      select max(c_age) from t_student where c_gender = '男';
      

    • min 求最小值函式

      select min(c_age) from t_student where c_gender = '女';
      

    • count 統計記錄總數

      1.   select count(*) from t_student;
      2.   select count(*) from t_student where c_gender = '女';

  9. 分組 分組就是將相同資料放到一起進行處理。 單純的分組是沒有意義的,需要配合聚合函式一起使用。 語法: select 分組的欄位名,聚合函式... from 表名 group by 分組欄位名 having 分組後的條件

注意:在執行 group by 分組時,select 後只能有被分組的欄位,不允許有其它欄位,除非這些欄位在聚合函式中

  1.   - 單欄位分組
  2.   ```sql
  3.   select c_gender from t_student group by c_gender;
  4.   ```
  5.   <img src='images/88.png'>
  6.    
  7.   - 多欄位分組(瞭解)
  8.   可以對多個欄位進行分組,作用同上,需要注意的是多欄位時,只有對應欄位完全相同,才能分為同一組
  9.   ```sql
  10.   select c_gender,c_address from t_student group by c_gender,c_address;
  11.   ```
  12.   <img src='images/89.png'>
  13.    
  14.   - group_concat()
  15.   作用:根據分組結果,使用group_concat()來獲取分組中指定欄位的集合
  16.   語法:group_concat(欄位名)
  17.   ```sql
  18.   select c_gender,group_concat(c_name) from t_student group by c_gender;s
  19.   ```
  20.   <img src='images/90.png'>
  21.    
  22.   - 分組和聚和函式使用
  23.   單純的使用分組並沒有實際意義,需要使用聚合函式對資料進行處理。
  24.   ```sql
  25.   select c_gender,max(c_age),min(c_age),sum(c_age),avg(c_age),count(*) from t_student group by c_gender;
  26.   select c_gender,max(c_age),min(c_age),sum(c_age),avg(c_age),count(c_age) from t_student group by c_gender;
  27.   ```
  28.   <img src='images/91.png'>
  29.    
  30.   - having條件子句
  31.   having 作用和 where 類似,用來去分組資料進行篩選
  32.   where 是對 form 表 中取資料時進行篩選
  33.   having 是對 group by 分組後的資料進行篩選
  34.   因為在執行順序上,在執行 where 時,分組還沒有執行
  35.   得先根據 where 的條件取出資料,才能去取出的資料進行分組。
  36.    
  37.   ```sql
  38.   select c_gender,group_concat(c_name) from t_student group by c_gender having c_gender = '女';
  39.   select c_gender,group_concat(c_name) from t_student where c_age > 50 group by c_gender having c_gender = '女';
  40.   ```
  41.    
  42.   <img src='images/92.png'>
  43.    
  44.   - 分組彙總(無大用,瞭解即可)
  45.   作用:會在分組下方,加一行,顯示彙總
  46.   語法:with rollup
  47.    
  48.   ```sql
  49.   select c_gender from t_student group by c_gender with rollup;
  50.   select c_gender,count(*) from t_student group by c_gender with rollup;
  51.    
  52.   ```
  53.   <img src='images/93.png'>

多表查詢資料

在資料庫操作中,資料往往不是存在一張表中的,同一個專案中,根據設計正規化,資料可能分散在不同的多張表中,這時查詢資料時,就需要多表查詢。

  1. 普通多表查詢(無意義) 作用:直接將表放在from後面,進行讀取。 語法:select 表名.欄位 ... from 表名1,表名2...

     select * from t_student,t_class;
    

    這種查詢方式沒有任何意義。 在查詢時,資料庫會將表1中的資料逐條和表2中的所有資料連線,組成一條新記錄。 查詢的結果為 M * N 條,實際就是笛卡爾積結果。

  2. 多表查詢連線條件 在多表個表進行查詢時,表與表之間應該是有有關係的,一般會以外來鍵的形式來建立表間的關係。 查詢時按照條件建立記錄的匹配規則。 比如學生表中儲存了學生的資訊和所在班級的ID,班級表中儲存了班級的資訊。 在查詢學生的班級資訊時,可以通過學生表中的班級ID和班級表中的ID匹配進行查詢

     select t_student.c_name,t_class.c_name  from t_student,t_class where t_student.c_class_id = t_class.c_id;
    

  3. 表別名 在多表操作時,由於表的名字比較長,在寫SQL語句時非常不方便。可以在查詢 時,給表起個別名,代替表名來操作 語法: select 別名.欄位名... from 表1 as 表1別名,表2 表2別名... [條件]

     select ts.c_name as '姓名' , tc.c_name '班級名' from t_student as ts,t_class tc where ts.c_class_id = tc.c_id;
    

  4. 內連線查詢 作用:查詢的結果為兩個表匹配到的資料 語法: select * from 表1 inner join 表2 on 表1.列 運算子 表2.列 圖示:  資料庫預設的連線方式就是內連線查詢, inner join 可以不顯示的寫出來。 這種連線方式會以笛卡爾積的形式進行連線。 所以在連線時,必須要給定連線條件。 連線條件使用 on 進行指定。儘量不要使用 where,where在其它連線方式時,指定的連線條件無效。

     select ts.c_name, tc.c_name from t_student as ts inner join t_class tc on ts.c_class_id = tc.c_id;
    

  1. 左連線查詢 作用:查詢的結果為根據左表中的資料進行連線,如果右表中沒有滿足條件的記錄,則連線空值。 語法: select * from 表1 left join 表2 on 表1.列 運算子 表2.列 圖示: 

     select ts.c_name, tc.c_name from t_student as ts left join t_class tc on ts.c_class_id = tc.c_id;
    

  1. 右連線查詢 作用:查詢的結果為根據右表中的資料進行連線,如果左表中沒有滿足條件的記錄,則連線空值。 語法: select * from 表1 right join 表2 on 表1.列 運算子 表2.列 圖示: 

     select ts.c_name, tc.c_name from t_student as ts right join t_class tc on ts.c_class_id = tc.c_id;
    

    在實際工作中,右連線使用的非常少,因為左連線完全可以替代右連線,在連線過程中,只需要調整表的順序即可。

  2. 子查詢 作用:作用:在一個 select 語句中,嵌入了另外一個 select 語句, 那麼被嵌入的 select 語句稱之為子查詢語句 語法: select * from 表1 where 條件 運算子 (select 查詢)

  • 外部那個select語句則稱為主查詢
  • 主查詢和子查詢的關係

    • 子查詢是嵌入到主查詢中
    • 子查詢是輔助主查詢的,要麼充當條件,要麼充當資料來源
    • 子查詢是可以獨立存在的語句,是一條完整的 select 語句
  • 標量子查詢 作用:子查詢返回的結果是一個數據(一行一列) 語法:主查詢 where 條件 比較運算子 (列子查詢)

    • 查詢班級中年齡大於平均年齡的學生資訊

      1. 查詢班級學生平均年齡
      2. 查詢大於平均年齡的學生
      select * from t_student where c_age > (select avg(c_age) from t_student);
      

  • 列級子查詢 作用:子查詢返回的結果是一列(一列多行) 語法:主查詢 where 條件 in (列子查詢)

    • 查詢所有學生所在班級的班級名稱

      1. 找出學生表中所有的班級 id
      2. 找出班級表中對應的名字
      select * from t_class where c_id in (select c_class_id from t_student);
      

  • 行級子查詢 作用:子查詢返回的結果是一行(一行多列) 語法:主查詢 where (欄位1,2,...) = (行子查詢)

    • 查詢班級年齡最大,所在班號最小的的學生

      1. 找出最大年齡和最小班號
      2. 找出年齡和班號滿足條件的學生
      select * from t_student where(c_age,c_class_id) = (select max(c_age),min(c_class_id) from t_student);
      

  1. 自連線查詢 作用:在查詢資料時,只有一張表,查詢時使用自己連線自己。 語法: select * from 表1 inner join 表2 on 表1.列 運算子 表2.列 where 條件

  2. 為什麼需要自連線

    以要設計表結構來儲存 全國 所有的省份和 全國所有的市

    • 設計省資訊的表結構provinces
    • id 省的編號
    • ptitle 省名稱

    • 設計市資訊的表結構citys

    • id 市編號
    • ctitle 市名稱
    • proid 市所屬的省的編號

    citys表的proid表示城市所屬的省,對應著provinces表的id值

    如果需要查詢一個省 比如廣東省對應的所有的時的資訊 ,我們可以使用兩個表連線查詢。

  1.   > 問題: 能不能將兩個表合成一張表呢?
  2.    
  3.   觀察兩張表發現,citys表比provinces表多一個列proid,其它列的型別都是一樣的。
  4.   這樣做的**好處**在於: 儲存的都是地區資訊,而且每種資訊的資料量有限,沒必要增加一個新表,或者將來還要儲存區、鄉鎮資訊,都增加新表的開銷太大。
  • 定義表areas,結構如下

    • id
    • atitle
    • pid

      關於這個表的說明:

    • 因為省沒有所屬的省份,所以可以填寫為null
    • 城市所屬的省份pid,填寫省所對應的編號id
    • 這就是自關聯,表中的某一列,關聯了這個表中的另外一列,但是它們的業務邏輯含義是不一樣的,城市資訊的pid引用的是省資訊的id
    • 在這個表中,結構不變,可以新增區縣、鄉鎮街道、村社群等資訊

      問題: 如果還是要查詢廣東省對應的所有的市的資訊,咱們應該怎麼做呢?

      areas表和自身進行連線這種形式的連線 就成為自連線。

  • 準備資料

    • 建立areas表的語句如下: 注意,表所在的資料庫字符集必須是utf8的,如果不是會匯入資料出錯
      1.   create table areas(
      2.   aid int primary key,
      3.   atitle varchar(20),
      4.   pid int
      5.   );
    • 從sql檔案中匯入資料
      source /home/python/Desktop/areas.sql;
      
  • 自查詢

    • 查詢一共有多少個省

      select count(*) from areas where pid is null;
      

    • 查詢省的名稱為“山西省”的所有城市

      select city.* from areas as city inner join areas as province on city.pid=province.aid where province.atitle='山西省';
      

    • 查詢市的名稱為“廣州市”的所有區縣

      select dis.* from areas as dis inner join areas as city on city.aid=dis.pid where city.ati