我有一组三个表:
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 :(得分: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"
答案 1 :(得分: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"
虽然它是三个语句,但它将作为单个结果集返回。
如果您将“作业”分成一个单独的表格,那么查询将变得更加容易。
我可以想象出以下几点:
Tables,TableTypes,Persons,Roles,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
这将使您的所有查询变得非常简单和直接,并使其可扩展(因此您可以在不破坏数据库的情况下为每个表添加更多角色)
答案 2 :(得分: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
)
这将为每个用户提供一行,指示用户所在的表(或为空)。
如果您确实只想要单个用户的直接列表,那么联合方法可能更受欢迎。但是,如果将为名册或用户运行此查询,我认为我的方法更好。