2009-04-24 3 views
3

나는 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_table, poker_table, computer_table) 다른 열 사람의 첫 번째/마지막 이름을 저장 굴러 다닌다.

내 모델에서는 한 개인이 여러 가지 작업을 수행 할 수 있습니다. 예를 들어 Joe Smith는 프로그래머로 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

Perphaps 질문 제목의 더 현명한 방법은 MySQL입니다. 여러 테이블에서 여러 행을 조인 할 수 있습니까? 그게 처음에 요청한 것입니다 ... 두 개 이상을 병합하지 않았습니다. 기준과 함께 "열"을 선택하십시오. – Victor

답변

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

데이터 모델은 차선책입니다. 고려 :

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 
) 

이 뜻을 :

말했다되고 그건
 
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이 테이블에서 여러 개의 좌석을 가질 수없는 경우 UNION이 성능 적중 일 수있는 중복을 제거하기 때문에 UNION ALL을 만들 수 있습니다.이 경우 UNION이 적합합니다. MySQL에 동일한 의미가 있는지 확실하지 않습니다. –

+0

노조를 신중히 선택했기 때문에. 그러나 OP는 이것이 일어날 수 있는지 없는지에 대해 명확하지 않습니다. – Tomalak

3

난 당신이 거기에서 다른 테이블에 가입 한 후 사용자 테이블로 시작해야한다고 생각 사용자 당 하나의 행을 제공하여 사용자가 어느 테이블에 있는지 (또는 널 (null)로 표시).

단일 사용자에 대해서만 스트레이트리스트를 원한다면 연합 방식이 바람직 할 수 있습니다. 그러나이 쿼리가 명단이나 사용자에 대해 실행되면 내 접근 방식이 더 좋습니다.

관련 문제