2009-04-24 115 views
3

我有一組三個表:MySQL:跨多個表的多列連接?

 
Dining_Tables; 
+--------------------+--------------+------+-----+---------+-------+ 
| Field    | Type   | Null | Key | Default | Extra | 
+--------------------+--------------+------+-----+---------+-------+ 
| dining_table  | int(11)  | NO | PRI | NULL |  | 
| bus_boy   | varchar(35) | NO |  | NULL |  | 
| waiter    | varchar(35) | NO |  | NULL |  | 
| server    | varchar(35) | NO |  | NULL |  | 
+--------------------+--------------+------+-----+---------+-------+ 

Poker_Tables; 
+--------------------+--------------+------+-----+---------+-------+ 
| Field    | Type   | Null | Key | Default | Extra | 
+--------------------+--------------+------+-----+---------+-------+ 
| poker_table  | int(11)  | NO | PRI | NULL |  | 
| dealer    | varchar(35) | NO |  | NULL |  | 
| pit_boss   | varchar(35) | NO |  | NULL |  | 
+--------------------+--------------+------+-----+---------+-------+ 

Computer_Tables; 
+--------------------+--------------+------+-----+---------+-------+ 
| Field    | Type   | Null | Key | Default | Extra | 
+--------------------+--------------+------+-----+---------+-------+ 
| computer_table  | int(11)  | NO | PRI | NULL |  | 
| programmer   | varchar(35) | NO |  | NULL |  | 
+--------------------+--------------+------+-----+---------+-------+ 

每行中都有一個與之關聯的全局唯一表ID:(dining_tablepoker_tablecomputer_table) 其他列存儲的人的名字/姓氏履行職責。

在我的模型中,一個人可以做多件事情。例如,喬·史密斯可能同時坐在computer_table作爲程序員,坐在poker_table作爲經銷商,並等待dining_table作爲服務員。

我的問題是這樣的: 我想要一個查詢,可以讓我檢索給定人的所有table_ids。具體來說,查詢會返回Joe Smith當前所在的列表table_ids

我可以做一些沿着這些路線:

 
select dining_table from Dining_Tables where 
     bus_boy = "Joe Smith" or 
     waiter = "Joe Smith" or 
     server = "Joe Smith"; 

select poker_table from Poker_Tables where 
     dealer = "Joe Smith" or 
     pit_boss = "Joe Smith"; 

select computer_table from Computer_Tables where 
     programmer = "Joe Smith"; 

然而,這三個單獨的查詢和我真的希望避免這樣做,如果可能的話。我可以在一個查詢中使用連接嗎?

+0

在問題的標題中採用更爲恰當的方式是MySQL:跨多個表的多「ROW」連接?這就是您首先要求的......您並未合併兩個或更多用條件選擇「列」。 – Victor 2013-08-04 01:01:45

回答

6

如果您想在單個查詢中返回它,您可以使用將這三個查詢合併爲一個的UNION語句。

select dining_table as Table from Dining_Tables where 
     bus_boy = "Joe Smith" or 
     waiter = "Joe Smith" or 
     server = "Joe Smith" 
UNION 
select poker_table as Table from Poker_Tables where 
     dealer = "Joe Smith" or 
     pit_boss = "Joe Smith" 
UNION 
select computer_table as Table from Computer_Tables where 
     programmer = "Joe Smith" 

雖然是三句話,它會返回一個結果集。

如果你將你的「工作」分隔成一個單獨的表格,它將使查詢變得更容易。

我能想象的線沿線的東西:

表,TableTypes,人物,角色,TableRoles

TableTypes 
ID TypeName 
----------------------- 
1  Dining 
2  Poker 
3  Computer 

Tables 
ID TableTypeID 
---------------------------- 
1  1 
2  1 
3  2 
4  3 
5  2 
6  3 

Persons 
ID Name 
--------------------------- 
1  Joe Smith 
2  Mary Belcher 
3  Norma Grey 


Roles 
ID RoleName 
----------------------------- 
1  Bus Boy 
2  Waiter 
3  Server 
4  Dealer 
5  Pit Boss 
6  Programmer 


TableRoles 
TableID RoleID PersonID 
----------------------------- 
1   1   1 
//etc 
//etc 

這將使所有的查詢非常簡單明瞭的,也使得它可擴展(因此您可以在不損壞數據庫的情況下爲每個表添加更多角色)

8

您的數據模型是次優的。試想一下:

 
Person  PersonRole  Role  Table 
------  ----------  ----  ----- 
Id*  PersonId*  Id*  Id* 
Name  RoleId*  Name  Name 
          TableId 

話雖這麼說...

select dining_table from Dining_Tables where 
     bus_boy = "Joe Smith" or 
     waiter = "Joe Smith" or 
     server = "Joe Smith" 
union 
select poker_table from Poker_Tables where 
     dealer = "Joe Smith" or 
     pit_boss = "Joe Smith" 
union 
select computer_table from Computer_Tables where 
     programmer = "Joe Smith" 
+0

對於SQL Server,您可能希望創建一個UNION ALL,因爲UNION刪除可能成爲性能命中的重複項......除非一個人可以在一個表中擁有多個席位,在這種情況下UNION是適當的。我不確定Mysql是否具有相同的語義。 – 2009-04-24 17:14:45

3

我想你應該有你的用戶表開始,然後從那裏加入到其他表:

SELECT U.user_id, d.dining_table, p.poker_table, c.computer_table 
FROM Users U 
LEFT JOIN Dining_Table D 
    ON D.bus_boy = U.user_id OR D.waiter = U.user_id or D.server = U.user_id 
LEFT JOIN Poker_Table P 
    ON P.dealer = U.user_id OR P.pit_boss = U.user_id 
LEFT JOIN Computer_Table C 
ON C.programmer = U.user_id 
WHERE U.Name = 'Joe Smith' 

-- only return rows with at least one table match 
-- or leave off to always return the user) 
AND NOT (
    d.dining_table IS NULL 
    AND p.poker_table IS NULL 
    AND c.computer_table IS NULL 
) 

這將給每個用戶一行,指示用戶在哪個表(或空)。

如果您真的只想爲單個用戶提供一個直線列表,那麼聯合方法可能是首選。但是,如果這個查詢將會爲名單或用戶運行,我認爲我的方法更好。