“条件”加入基于场值?

时间:2012-12-20 17:20:43

标签: php mysql sql database-design relational-database

我正在处理的网站有3种不同类型的用户:管理员,申请人,审核人。这些组中的每一个都将具有一些需要存储的基本信息(名称,ID,电子邮件等)以及每个组独有的数据。我已经创建了一个users表以及一个用于存储其唯一数据的特定组的表。

  • 用户:id,f_name,l_name,email,user_type
  • users_admin:id,user_id,office,emp_id
  • users_applicant:id,user_id,dob,address
  • users_reviewer:id,user_id,active_status,address,phone

如果user_type为“1”(申请人)的用户登录,我需要JOINusers_applicants表来检索他们的完整记录。我尝试使用UNION,但我的表格列有很多不同。

有没有办法根据用户的类型编写一个条件查询JOIN到正确的表?我完全错误地采取了这种方式吗?

提前感谢您的帮助!

3 个答案:

答案 0 :(得分:2)

嗯,最后你的桌子已经存在缺陷。为什么甚至为每种类型都有一张桌子?为什么不将所有这些字段放入users表,或者可能是user_details表(如果你真的想要一个非常规数据字段的额外表)?目前,您实际上是从关系角度创建了4个独立的用户表。

那么为什么类型表有代理键呢?为什么user_id已经是(唯一的)主键?

如果你改变了,你只需要用户ID来检索你想要的数据,而你已经得到了(或者你甚至无法检索用户类型)。

答案 1 :(得分:1)

您可以通过编程方式执行此操作,也可以使用一系列CASELEFT JOIN来执行此操作。

为简单起见,我们使用表users来执行此操作,您可以在其中使用类型1(普通用户),2(高级用户)或3(管理员)的用户。普通用户有电子邮件但没有电话,高级用户有一个地址和一个被称为“超级大国”的字段,管理员有一个电话号码,没有别的。

由于您希望对所有人使用相同的SELECT,当然您需要将所有这些内容放在SELECT中:

SELECT user.id, user.type, email, address, superpower, telephone

然后您需要LEFT JOIN来恢复这些

FROM user
LEFT JOIN users_data ON (user.id = users_data.user_id)
LEFT JOIN power_data ON (user.id = power_data.user_id)
LEFT JOIN admin_info ON (user.id = admin_info.user_id)

现在“未使用”字段为NULL,但您可以提供默认值:

SELECT
    CASE WHEN user.type = 0 THEN email ELSE 'nobody@nowhere.com' END AS email,
    CASE WHEN user.type = 1 OR user.type = 2 THEN ... ELSE ... END as whatever,
    ...

您可以放入WHERE本身的具体JOIN条件,例如如果您只想要J扇区的管理员,可以使用

LEFT JOIN admin_info ON (user.id = admin_info.user_id AND admin_info.sector = 'J')

总查询时间不应该太糟糕,因为大多数JOIN都会返回很少(如果你指定了一个用户ID,它们实际上会返回 nothing 非常快)。

你也可以使用UNION做同样的事情,这会更快:

SELECT user.id, 'default' AS email, 'othermissingfield' AS missingfieldinthistable,
  ... FROM user JOIN user_data ON (user.id = user_data.user_id)
  WHERE ...
UNION
SELECT user.id, email, 'othermissingfield' AS missingfieldinthistable,
  ... FROM user JOIN power_data ON (user.id = power_data.user_id)
  WHERE ...
UNION
  ...

现在,如果您指定用户ID,除了一个查询之外的所有查询都将非常快速地失败。每个查询都具有相同的WHERE重复加上任何特定于表的条件。 UNION版本的可维护性较低(除非您以编程方式生成),但应该稍微快一点。

在所有情况下,建议您在相应字段中保留更新的索引。

答案 2 :(得分:1)

相反,我会建议你重建这样的表结构。

创建表

users_types : 
id 
type

然后使用外键创建另一个表用户

users :     
id 
f_name 
l_name 
email 
office 
emp_id 
dob 
address 
active_status 
phone 
users_types_id

现在,当您需要在特定用户不需要的字段中插入数据插入null时。你可以简单地根据id获取记录。同样使用左连接将为您提供用户类型的名称。