Board logo

標題: 9-1 認識DML指令(9-1-1 Select指令) [打印本頁]

作者: 小誌    時間: 2011-4-21 18:49     標題: 9-1 認識DML指令(9-1-1 Select指令)

9-1   認識DML指令
DML:資料處理語言,為SQL中的資料處理指令群,包括Select(查詢)、Insert(新增)、Delete(刪除)、Update(修改)等指令。

9-1-1   Select指令
Select指令您不陌生吧!在上一章中,筆者就做了很多的介紹,現在筆者要介紹的是Select指令的進階應用:

跨資料表查詢
筆者現在舉一個實例來說明:在LEAVE資料庫中含有「factoryman(員工名單)」、「laik(休假記錄)」這兩個資料表:
[attach]5679[/attach]
圖9-1  範例資料庫內的資料表。

現在我要從「factoryman(員工名單)」資料表中挑出「laik(休假記錄)」資料表內休假「天數」大於三天的員工資料,如果單純的使用一個Select指令是無法達到這個要求的,因此我們必須使用兩個Select指令!首先我們先利用下列敘述找出「laik(休假記錄)」資料表內休假「天數」大於三天的員工資料:
  1. Select 姓名  From  laik Where  天數>3
複製代碼
這樣的查詢結果就成為一個「虛擬」資料表(集),接著我們要利用這個「虛擬」資料表(集)的資料為進階篩選條件值,篩選出「factoryman(員工名單)」資料表中被點名休假超過3天的員工資料:
  1. Select  *  From  factoryman where 姓名 In
  2. (Select 姓名 From laik Where 天數>3)
複製代碼
如此,就可以從「員工名單」資料表中挑出「休假記錄」資料表內休假「天數」大於三天的員工資料!
[attach]5680[/attach]
圖9-2   SubQuery。
上圖中:未加框部分的Select指令敘述中含有另一段被框線框起來的Select指令敘述,這種雙Select指令組合的敘述稱之為「SubQuery」!
作者: 小誌    時間: 2011-4-21 18:50

當我們將這「進階查詢指令」應用於程式中將可得到圖9-3的結果,被條列出來的員工都是休假天數超過三天者。
ex09_01.php
  1. <?
  2.     $conn = mysql_connect("localhost", "root", "12345a");
  3.     if(@mysql_select_db("LEAVE", $conn))
  4.      {
  5.       //指定提取資料的校對字元表
  6.       mysql_query("set character set big5");
  7.       //資料庫存在,建立SQL命令字串
  8.       $SQL="Select  *  From  Factoryman where 姓名 In" .
  9.             "(Select 姓名 From laik Where 天數>3)";      //將回傳結果存放於變數中
  10.       $datalist=mysql_query($SQL);
  11.       //取得欄位數量
  12.       $fieldnum=mysql_num_fields($datalist);
  13. ?>
  14. <html>
  15. <head>
  16. <meta http-equiv="Content-Type" content="text/html; charset=big5">
  17. <title>範例ex09_01</title>
  18. </head>
  19. <center><table border=1 width=100%>
  20. <?
  21. /**************列出欄位抬頭***************/
  22. echo "<tr>";     
  23.       for ($x=0 ;$x<$fieldnum;$x++)
  24.          {
  25.           echo "<td>" . mysql_field_name($datalist,$x) . "</td>";
  26.          }
  27. echo "</tr>";   
  28. /**************列出欄位資料***************/
  29.       //將資料錄轉換為欄位陣列集合
  30.       while ($fielddatas=mysql_fetch_array($datalist))
  31.           {
  32.              //輸出欄位資料
  33.              echo "<tr>";
  34.              for ($x=0;$x<$fieldnum;$x++)
  35.                 {
  36.                  echo "<td>" . $fielddatas[$x] . "</td>";
  37.                 }
  38.              echo "</tr>";  
  39.           }
  40. ?>
  41. <table></body>
  42. </html>
  43. <?
  44.      }
  45.     else
  46.      {
  47.       echo "資料庫不存在";
  48.      }
  49. ?>
複製代碼
[attach]5681[/attach]
圖9-3  範例ex09_01.php。
作者: 小誌    時間: 2011-4-21 18:51

分組統計 Group By
在「laik」資料表內,我們可以發現員工休假的次數可能不只一次,也許請了一次病假,過了幾天又請了事假,因此休假的記錄就不只一次:
[attach]5682[/attach]
圖9-4   多次休假記錄。

如果我們希望得知員工的總休假天數那我們可以使用「SUM」函數來統計:
  1. Select Sum(天數) AS 員工休假總天數 From laik
複製代碼
可是我們得到的是全部員工的休假天數ㄚ,那我希望分別得知每一位員工的總休假天數,那又改如何處理?這個時候我們就可以利用「Group By」指令來進行分組統計:
  1. Select 姓名,Sum(天數) AS 休假總天數 From laik Group By 姓名
複製代碼
執行上列的指令敘述後,結果如下圖(範例ex09_02.php):
[attach]5683[/attach]
圖9-5   分組統計之執行畫面。
作者: 小誌    時間: 2011-4-21 18:52

分組統計並不限定使用於單一欄位,資料表中的每一個欄位都可成為分組的依據,同時,我們也可以使用多個欄位來作為分組的依據,例如下列的分組指令敘述:
[attach]5684[/attach]
圖9-6   多欄分組。

[attach]5685[/attach]
圖9-7  範例ex09_03.php。
作者: 小誌    時間: 2011-4-21 18:54

分組篩選
Group By指令了可以用來排序外,也可以同時加上排序指令來進行資料排序,例如:我們以「假別」為分組依據,利用Order By指令針對休假天數來排序:
  1. Select 假別,Sum(天數) AS 休假總天數 From laik Group By假別 Order By休假總天數
複製代碼
除了排序之外,我們還可加上Where指令先進行資料篩選後再進行分組與排序:
  1. Select 假別,Sum(天數) AS 休假總天數 From laik Where
  2. 年=86 Group By假別 Order By休假總天數
複製代碼
上兩式的敘述執行結果如圖9-8,要特別注意到一點:使用Where指令進行篩選,只能夠在原始資料的情況下進行篩選的動作,也就是說,篩選資料的動作必須發生於分組動作之前,不能在分組動作完成之後才使用Where指令進行分組結果的篩選!
[attach]5686[/attach]
圖9-8  圖左為分組與排序;圖右為資料篩選後再進行分組與排序。
作者: 小誌    時間: 2011-4-21 18:55

在分組動作完成之後,我們還要對分組結果的資料進行篩選時,我們該如何處理?切記:不能使用Where指令!否則您會見到下列的錯誤訊息:
[attach]5687[/attach]
圖9-9   Where篩選不能在分組完成之後。

如果在分組動作完成之後才進行資料篩選的動作必須使用「Having」指令,例如下例:(範例ex09_04.php)
  1.       //資料庫存在,建立SQL命令字串
  2.       $SQL="Select 年,姓名,假別,sum(天數) AS 年休假數 From laik " .
  3.      "Group By 年,姓名,假別 HAVING 年=86";
  4.       //將回傳結果存放於變數中
  5.       $datalist=mysql_query($SQL);
  6.       //取得欄位數量
  7.       $fieldnum=mysql_num_fields($datalist);
複製代碼
[attach]5688[/attach]
圖9-10  使用Having指令篩選分組結果。
作者: 小誌    時間: 2011-4-21 18:56

那我可不可以更改篩選的條件值?可以,您不但可以使用「虛擬」欄位為篩選的根據,如下例:
  1. Select 年,姓名,假別,sum(天數) AS 年休假數  From 休假記錄
  2. Group By 年,姓名,假別 Having 年休假數>2  
複製代碼
上式中的「年休假數」雖然是「Sum(天數)」的計算結果,它也是一個「虛擬」欄位,不是資料庫中的真實欄位,但是卻能用來做為篩選的根據。
如果您要使用「計算」欄位做為篩選根據,也可以撰寫成下式:(範例ex09_05.php)
  1. SQL="Select 年,姓名,假別,sum(天數) AS 年休假數 From 休假記錄 " &_
  2.      "Group By 年,姓名,假別 Having sum(天數)>2"
  3. CMD.CommandText=SQL
複製代碼
執行結果如下圖:
[attach]5689[/attach]
圖9-11  範例ex09_05.php。




歡迎光臨 麻辣家族討論版版 (http://forum.twbts.com/)