2010-06-23 53 views
2

我想這個查詢是一個基本的,我應該知道更多關於SQL,但沒有做很多與連接,但我認爲這是解決方案。如何合併2個SQL表中的行而不重複行?

我所擁有的是一張人們的桌子和他們所擁有的工作角色表。一個人可以有多個工作,我希望有一組結果,每個人包含他們的詳細信息和工作角色。

兩個示例表(people和job_roles)在下面,因此您可以更容易地理解問題。

人民

 
id | name | email_address | phone_number 
1 | paul | [email protected] | 123456 
2 | bob | [email protected] | 567891 
3 | bart | [email protected] | 987561 

job_roles

 
id | person_id |  job_title | department 
    1 |  1  |  secretary | hr 
    2 |  1  |  assistant | media 
    3 |  2  |  manager | IT 
    4 |  3  | finance clerk | finance 
    4 |  3  |  manager | IT 

讓我可以輸出的每個人,像這樣的

 
Name: paul 
Email Address: [email protected] 
Phone: 123456 
Job Roles: 
Secretary for HR department 
Assistant for media department 
_______ 
Name: bob 
Email address: [email protected] 
Phone: 567891 
Job roles: 
Manager for IT department 

自己的角色所以,我怎麼會得到每個人的信息(從人員表格)和他們的工作細節(從job_roles表格)輸出到上面的例子。我想這可能是某種將他們的工作和相關部門合併成一個可以分割輸出的工作列的方式,但也許有更好的方法,sql會是什麼樣子?

感謝

保羅

PS這將是一個MySQL數據庫,如果有什麼差別

回答

2

RE:

我希望SQL可以做聰明事 ,並很好地加入行一起 所以我基本上是有工作 列在它是人的就業機會。

你可以得到相當接近與

SELECT p.id, p.name, p.email_address, p.phone_number, 
group_concat(concat(job_title, ' for ', department, ' department') SEPARATOR '\n') AS JobRoles 
FROM People AS p 
    INNER JOIN job_roles AS r ON p.id = r.person_id 
GROUP BY p.id, p.name, p.email_address, p.phone_number 
ORDER BY p.name; 
+1

感謝這是我最終使用的,它運作良好。 – AdrenalineJunky 2010-07-22 08:21:51

+0

這是非常聰明和方便的知道,但我仍然喜歡在PHP中進行正常的連接和格式化數據。如果您想要更改格式(例如,在作業角色之間添加
),您必須修改SQL查詢。 GROUP_CONCAT刪除了數據庫邏輯和表示的分離。這也使得單元測試更加困難。 – dave1010 2010-07-27 12:20:40

3

它看起來像一個直接的連接:

SELECT p.*, j.* 
    FROM People AS p INNER JOIN Roles AS r ON p.id = r.person_id 
ORDER BY p.name; 

的的其餘部分工作正在格式化;這最好由報告包完成。


感謝您的快速反應,這似乎是一個良好的開端,但你得到的多行每人像(你必須想象這是因爲你似乎並不能夠在註釋格式的表):

id | Name | email_address | phone_number | job_role | department 
1 | paul | [email protected] | 123456  | secretary | HR 
1 | paul | [email protected] | 123456  | assistant | media 
2 | bob | [email protected] | 567891  | manager | IT 

我想每人一排最好在它所有的工作角色,如果這是可能的嗎?

它取決於您的DBMS,但大多數可用的不支持RVAs - 關係值屬性。你想是有結果的像與用戶相關聯的表中的職位和部門的部分:

+----+------+------------------+--------------+------------------------+ 
| id | Name | email_address | phone_number | dept_role   | 
+----+------+------------------+--------------+------------------------+ 
| |  |     |    | +--------------------+ | 
| |  |     |    | | job_role | dept | | 
| 1 | paul | [email protected] | 123456  | | secretary | HR | | 
| |  |     |    | | assistant | media | | 
| |  |     |    | +--------------------+ | 
+----+------+------------------+--------------+------------------------+ 
| |  |     |    | +--------------------+ | 
| |  |     |    | | job_role | dept | | 
| 2 | bob | [email protected] | 567891  | | manager | IT | | 
| |  |     |    | +--------------------+ | 
+----+------+------------------+--------------+------------------------+ 

這準確地表示您想要的信息,但通常不是一種選擇。

因此,接下來會發生什麼取決於您的報告生成工具。使用我最熟悉的(Informix ACE,可從IBM獲得用於Informix DBMS的Informix SQL的一部分),您只需確保數據已排序,然後打印名稱,電子郵件地址和電話號碼在報告的'BEFORE GROUP of ID'部分中,在'ON EVERY ROW'部分中,您將只處理(打印)角色和部門信息。

將報告格式與數據檢索操作分開通常是一個好主意;這是一個必要的例子,除非你的數據庫管理系統有不尋常的功能來幫助選擇數據的格式。


哦,親愛的,聽起來很複雜,不是我可以在一個PHP頁面MySQL數據庫上輕鬆地運行?

RVA的東西 - 你是對的,那不適用於MySQL和PHP。

另一方面,有數百萬的報告(意味着格式化爲向用戶呈現的查詢的結果)大致這樣做。他們的技術術語是'Control-Break Report',但基本思想並不難。

您保留上次處理的'id'號碼的記錄 - 您可以將其初始化爲-1或0. 噹噹前記錄具有與先前號碼不同的id號碼時,則您有一個新用戶,您需要爲新用戶啓動一組新的輸出行並打印名稱,電子郵件地址和電話號碼(並更改最後處理的ID號)。當前記錄具有相同的ID號碼時,您所做的只是處理工作角色和部門信息(而不是名稱,電子郵件地址和電話號碼)。當ID號碼改變時發生'break'。在單一控制水平的情況下,這並不難;如果你有4個或5個級別,你必須做更多的工作,這就是爲什麼有報告包來處理它。

所以,這並不難 - 它只是需要一點小心。

+0

+1:打敗我,所以我只需添加(此鏈接關於直觀地表示JOINs)[http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html] – 2010-06-23 20:06:32

+0

感謝您的快速響應,這似乎是一個好開始,但你會得到每個人喜歡多行(你必須想象這是一張桌子,因爲你似乎無法在評論中格式化): ID |名稱| email_address | phone_number | job_role |部門 1 | paul | [email protected] | 123456 |祕書| HR 1 | paul | [email protected] | 123456 |助理|媒體 2 | bob | [email protected] | 567891 |經理| IT 如果可能的話,我希望每個人都有理想的一行工作角色嗎? – AdrenalineJunky 2010-06-23 20:20:32

+0

哦,親愛的,聽起來很複雜,而不是我可以輕鬆地在PHP頁面的mySQL數據庫上運行? – AdrenalineJunky 2010-06-23 21:12:03

0

這樣做你想要的方式將意味着結果集數組可能會有無限的列,這將是非常混亂。例如,您可以將作業表加入10次,並獲得job1,job2,... job10。

我會做單一連接,然後使用PHP來檢查名稱ID是否從1行到下一個相同。

+0

謝謝,這是我剛纔的結論,但希望SQL能夠聰明地做些事情,並且將這些行很好地結合在一起,所以我基本上已經有了一個工作列,並且有人在其中工作。 – AdrenalineJunky 2010-06-23 21:13:40

0

的一種方式可能是左外連接的表,然後向上它們加載到一個數組使用

$people_array =array(); 
while($row1=mysql_fetch_assoc($extract1)){ 
$people_array[] = $row1; 
} 

,然後遍歷使用

for ($x=0;$x<=sizeof($people_array;) 
    { 
echo $people_array[$x][id]; 
echo $people_array[$x][name]; 

for($y=0;$y<=$number_of_roles;$y++) 
{ 
echo $people_array[$x][email_address]; 
echo $people_array[$x][phone_number]; 
    $x++; 
} 
    } 

您可能需要玩查詢一點和循環,但它應該做一般你想要的。對於上面的工作,每個人都必須具有相同數量的角色,但是您可以填寫表格中的空白。

+0

好主意,但組concat似乎是一個更乾淨的解決方案。 – AdrenalineJunky 2010-07-22 08:22:37