close

我這個標題我還想了一下要怎麼下

下太複雜我怕大家又看不太懂,還有搜尋引擎關鍵字的問題

(題外話......)

 

這個用看的不會懂,做過才知道其中的奧妙

--------------------------------------------------------------------------

問題

問題是這樣的

 

假設說,我有個資料庫,分別存了A表格 B表格 C表格 ......

都是主鍵(Primary Key)+外鍵(Foreign Key)的格式

這幾張表都有外來鍵只向同一張表格的主鍵

也就是

A表格

A_id(主鍵)  A_name  data ......

B表格

B_id(主鍵)   A_id(外來鍵)   data ......

C表格

C_id(主鍵)   A_id(外來鍵)   data ......

 

如今

 

我想要個別統計一下資料的狀況

 

最後呈現的欄位是這樣
A_id    A_name   B_count  C_count

 

這對我們來說不是難事

所以我們在資料庫下了這些SQL  (以下使用MySQL的格式表示)

 

對表格B做統計
SELECT `A_id`, COUNT(`B_id`) as `B_count` FROM `tableB` GROUP BY `A_id`;

 

得到
A_id    B_count  的欄位

 

對表格B做統計
SELECT `A_id`, COUNT(`C_id`) as `C_count` FROM `tableC` GROUP BY `A_id`;

 

得到
A_id    C_count  的欄位

 

問題來了

我們有學過JOIN,他們都有A_id
我們如何把他們另外統計的二張表格合起來

還要顯示A表格的其他內容

 

你要如何做?

 

--------------------------------------------------------------------------

第一,我可能會想到在JOIN的過程中

不能直接JOIN起來的話

好歹列數也要一致相同吧

所以我改這樣下

SELECT `A_id`, `A_name`, COUNT(`tableB`.`A_id`) as `B_count` FROM `tableA` LEFT JOIN `tableB` ON `tableA`.`A_id`=`tableB`.`A_id` GROUP BY `tableA`.`A_id`;

SELECT `A_id`, `A_name`, COUNT(`tableC`.`A_id`) as `C_count` FROM `tableA` LEFT JOIN `tableC` ON `tableA`.`A_id`=`tableC`.`A_id` GROUP BY `tableA`.`A_id`;

 

 

使用LEFT JOIN是因為INNER JOIN是有對到資料才會出現

而LEFT JOIN才會顯示Count是零的狀況

 

這樣也不盡人意......

 

 

--------------------------------------------------------------------------

解答

找好久才找到這個解答

我個人認為其重要性接近死背這個架構

 

SELECT `A_id`, `A_name`,

(SELECT COUNT(*) FROM `tableB` WHERE  `tableB`.`A_id`=`tableA`.`A_id`) AS `B_count`,  

(SELECT COUNT(*) FROM `tableC` WHERE  `tableC`.`A_id`=`tableA`.`A_id`) AS `C_count`,  

FROM `tableA`;

 

這個架構叫做

關聯子查詢

SQL語句裡面跟外面有產生關聯的

但是光看問題不會馬上想到這個架構

 

 

解釋

簡單來說一句SQL語法做了三個動作

 

從刮號裡面先看好了

裡面有二句SQL語法,看起來像是獨立的但不能跑

會有這個錯誤

#1054 - Unknown column 'tableA.A_id' in 'where clause'

因為他找不到tableA在哪裡

 

 

SELECT COUNT(*) FROM `tableB` WHERE  `tableB`.`A_id`=`tableA`.`A_id`

這句的意思是計算tableB總共有幾筆

我們有學到在WHERE裡面打上

`tableB`.`A_id`=`tableA`.`A_id`

意思就是要讓表格合併起來 (像是INNER JOIN)

 

----------------------------------------------------

*TIPS:

 

WHERE id=id能獨立跑的是這個

SELECT `tableA`.*, `tableB`.* FROM `tableA`, `tableB` WHERE `tableB`.`A_id`=`tableA`.`A_id`

用INNER JOIN 改寫變成

SELECT `tableA`.*, `tableB`.* FROM `tableA`INNER JOIN `tableB` ON `tableB`.`A_id`=`tableA`.`A_id`

 

----------------------------------------------------

在來就是外面那層

SELECT `A_id`, `A_name`, (......) AS `B_count`,  (......) AS `C_count`,  FROM `tableA`;

就只有簡單的撈整張表格出來而已

 

AS就是做欄位別名

整個SQL語句要做為一個欄位賦予別名

那該SQL語句必須資料輸出一個欄位而已

這裡輸出COUNT(*)剛好只有一欄,符合規定

 

----------------------------------------------------

其它範例

 

有個問卷的系統,表格長這樣

這個學生詢問了向各種對象,問各種不同的問題,放在不同的表格

而如今他想要把他的問題做統計

 

欄位名稱如下

Student(id,name,mykad,...)
Customer Service(id, Q1,Q2,Q3,date)
Instructor(id, Q1,Q2,Q3,date)
Runner(id, Q1,Q2,Q3,date)

SQL語法如下:

SELECT A.name, A.mykad, 

(select count(*) from customerservice B where B.id = A.id and B.Q1='Excellent') AS E, 
(select count(*) from customerservice C where C.id = A.id and C.Q1='Satisfaction') AS S,
(select count(*) from customerservice D where D.id = A.id and D.Q1='Poor') AS P
FROM student A

就會輸出欄位

name   mykad  E  S  P

 

這裡的參考資料一定要看,他寫的比我還要詳細

http://stackoverflow.com/questions/1279569/sql-combine-select-count-from-multiple-tables
http://www.daniweb.com/software-development/legacy-and-other-languages/threads/352342

arrow
arrow
    全站熱搜

    Johnny 鋼鍊 發表在 痞客邦 留言(1) 人氣()