2012-10-29 24 views
2

我有用戶表:電腦用戶有很多計算機,計算機有不同的表中有很多屬性,最好的方法來加入?

USERS: 
ID | NAME | 
---------------- 
1 | JOHN | 
2 | STEVE | 

一個表:磁碟機

PROCESSORS: 
ID | NAME    | 
--------------------------- 
27 | PROCESSOR TYPE 1 | 
28 | PROCESSOR TYPE 2 | 

和表:

COMPUTERS: 
ID | USER_ID | 
------------------ 
13 |  1  | 
14 |  1  | 

用於處理器的表

HARDDRIVES: 
ID | NAME    | 
---------------------------| 
35 | HARDDRIVE TYPE 25 | 
36 | HARDDRIVE TYPE 90 | 

中的每個計算機可具有的許多屬性從不同屬性表(處理器,磁碟機等),所以我有交叉點表這樣的,將屬性鏈接到計算機:

COMPUTER_PROCESSORS: 
C_ID | P_ID | 
--------------| 
13 | 27 | 
13 | 28 | 
14 | 27 | 

COMPUTER_HARDDRIVES: 
C_ID | H_ID | 
--------------| 
13 | 35 | 

所以用戶JOHN,ID爲1擁有計算機13和14.計算機13具有處理器27和28,並且計算機13具有硬盤驅動器35.計算機14具有處理器27並且不具有硬盤驅動器。

給定一個用戶的ID,我想檢索一個用戶的計算機列表與每個計算機的屬性。

我已經想通了查詢,讓我有點結果的:

SELECT computers.id, processors.id AS p_id, processors.name AS p_name, harddrives.id AS h_id, harddrives.name AS h_name, 
FROM computers 

JOIN computer_processors ON (computer_processors.c_id = computers.id) 
JOIN processors ON (processors.id = computer_processors.p_id) 

JOIN computer_harddrives ON (computer_harddrives.c_id = computers.id) 
JOIN harddrives ON (harddrives.id = computer_harddrives.h_id) 

WHERE computers.user_id = 1 

結果:

ID | P_ID | P_NAME   | H_ID | H_NAME   | 
----------------------------------------------------------- 
13 | 27 | PROCESSOR TYPE 1 | 35 | HARDDRIVE TYPE 25 | 
13 | 28 | PROCESSOR TYPE 2 | 35 | HARDDRIVE TYPE 25 | 

但是這有幾個問題...

  1. 計算機14不顯示,因爲它沒有硬盤。 我可以以某種方式創建一個OUTER JOIN以確保所有計算機都顯示出來,即使這些計算機沒有某些屬性?

  2. 計算機13顯示了兩次,兩個硬盤都有相同的硬盤偵聽。當更多的屬性添加到計算機(如3塊RAM)時,爲該計算機返回的行數變得非常大,並且它使得必須將結果排序在應用程序代碼中。 我可以以某種方式進行查詢,將兩個返回的行分組在一起?或者在第二行的h_name列中返回NULL的查詢,以便返回的所有值都是唯一的?

編輯: 我想回是這樣的:

ID | P_ID | P_NAME   | H_ID | H_NAME   | 
----------------------------------------------------------- 
13 | 27 | PROCESSOR TYPE 1 | 35 | HARDDRIVE TYPE 25 | 
13 | 28 | PROCESSOR TYPE 2 | 35 | NULL    | 
14 | 27 | PROCESSOR TYPE 1 | NULL | NULL    | 

或者任何結果可以很容易地把它變成一個數組這樣

[13] => 
    [P_NAME] => 
     [0] => PROCESSOR TYPE 1 
     [1] => PROCESSOR TYPE 2 
    [H_NAME] => 
     [0] => HARDDRIVE TYPE 25 


[14] => 
    [P_NAME] => 
     [0] => PROCESSOR TYPE 1 
+0

你怎麼連接電腦,處理器和磁碟機表,因爲我沒有看到任何公共列 – AnandPhadke

+0

你能展示你想要得到的最終結果嗎? –

回答

4

使用LEFT JOIN而不是INNER JOIN。這兩個連接彼此不同。 INNER JOIN,您當前使用的是)僅返回表格兩邊至少有一個匹配的記錄。這就是爲什麼computer 14不應該這樣,因爲它在表COMPUTER_HARDDRIVES上沒有匹配。 LEFT JOIN另一方面,返回左側表中的所有記錄是否在表的另一側不匹配。

SELECT a.ID AS UserID, 
     a.Name as UserName, 
     b.ID as ComputerID, 
     d.ID as ProcessorID, 
     d.Name as ProcessorName, 
     f.ID as HardDriveID, 
     f.name as HardDriveName 
FROM users a 
     INNER JOIN computers b 
      ON a.ID = b.user_ID 
     LEFT JOIN computer_processors c 
      ON b.ID = c.C_ID 
     LEFT JOIN PROCESSORS d 
      ON c.p_ID = d.ID 
     LEFT JOIN COMPUTER_HARDDRIVES e 
      ON b.ID = e.c_ID 
     LEFT JOIN HARDDRIVE f 
      ON e.h_ID = f.ID 
WHERE a.ID = 1 

既然你要的行groupt在一起,遵守前面走GROUP_CONCAT()功能的優勢。基本上,它是它的列的值組合成逗號分隔值

SELECT a.ID AS UserID, 
     a.Name as UserName, 
     b.ID as ComputerID, 
     GROUP_CONCAT(DISTINCT d.ID) as ProcessorID, 
     GROUP_CONCAT(DISTINCT d.Name) as ProcessorName, 
     GROUP_CONCAT(DISTINCT f.ID) as HardDriveID, 
     GROUP_CONCAT(DISTINCT f.name) as HardDriveName 
FROM users a 
     INNER JOIN computers b 
      ON a.ID = b.user_ID 
     LEFT JOIN computer_processors c 
      ON b.ID = c.C_ID 
     LEFT JOIN PROCESSORS d 
      ON c.p_ID = d.ID 
     LEFT JOIN COMPUTER_HARDDRIVES e 
      ON b.ID = e.c_ID 
     LEFT JOIN HARDDRIVE f 
      ON e.h_ID = f.ID 
WHERE a.ID = 1 
GROUP BY UserID, UserName, ComputerID 
+0

嗨,謝謝你的幫助,兩種方法都很好用!雖然我是一個擔心GROUP_CONCAT(DISTINCT ...)的小角色,因爲它使用逗號分隔這些值,並且我列中的某些值可能已經有一個逗號(例如'processor type 25,xx' ),然後從那裏排序將非常困難。我想我會採用第一種方法,然後在應用程序代碼中對所有內容進行排序。你會選擇哪一種方法? – acrmuui

+0

實際上,您不必擔心分隔符,因爲您可以更改它,也可以在'group_concat'中對其進行排序。 [*點擊此處查看演示*](http://sqlfiddle.com/#!2/5bca8/2)。 –

+0

[SQL小提琴演示(GROUP_CONCAT與ORDER BY和SEPARATOR更改)](http://sqlfiddle.com/#!2/5bca8/5) –

0
select u.ID user_id, 
     u.name user_name 
     p.id, 
     p.name, 
     h.id, 
     h.name 
from USERS u join COMPUTERS c 
on u.id=c.USER_ID 
join PROCESSORS p 
on c.id=p.id 
join HARDDRIVES h 
on c.id=h.id 
where u.id=1 
1
SELECT computers.id, processors.id AS p_id, processors.name AS p_name, harddrives.id AS h_id, harddrives.name AS h_name 
FROM computers 

LEFT JOIN computer_processors ON (computer_processors.c_id = computers.id) 
LEFT JOIN processors ON (processors.id = computer_processors.p_id) 

LEFT JOIN computer_harddrives ON (computer_harddrives.c_id = computers.id) 
LEFT JOIN harddrives ON (harddrives.id = computer_harddrives.h_id) 

WHERE computers.user_id = 1 
3

Tr y:

SELECT computers.id, 
     group_concat(distinct processors.id) AS p_ids, 
     group_concat(distinct processors.name) AS p_names, 
     group_concat(distinct harddrives.id) AS h_ids, 
     group_concat(distinct harddrives.name) AS h_names 
FROM computers 
JOIN computer_processors ON (computer_processors.c_id = computers.id) 
JOIN processors ON (processors.id = computer_processors.p_id) 
LEFT JOIN computer_harddrives ON (computer_harddrives.c_id = computers.id) 
LEFT JOIN harddrives ON (harddrives.id = computer_harddrives.h_id) 
WHERE computers.user_id = 1 
group by computers.id 
+0

非常感謝您的幫助! – acrmuui

相關問題