SQL查询根据给定列中的值连接不同的表?

时间:2014-02-14 11:09:04

标签: sql database

我正在为我的网站设计域模型和数据映射器系统。系统具有不同类型的用户域对象,具有用于管理员,mod和禁止用户的子类的用户的基类。每个域对象都使用名为“users”的表中的数据,而子类有一个额外的表来存储admin / mod / banned信息。用户类型由表'users'中名为'userlevel'的列确定,其值为3表示管理员,2表示mod,1表示注册用户,-1表示禁止用户。

现在,当我为我的网站工作成员列表功能时出现问题,因为成员列表应该从数据库加载所有用户(使用分页,但现在不用担心)。问题是我想从基本用户表和附加的admin / mod / banned表加载数据。如您所见,注册用户没有额外的表来存储额外的数据,而对于admin / mod / banned用户,表是不同的。而且,这些表中的列也不同。

那么我应该如何使用SQL查询处理这种情况?我知道我只需从基本用户表中选择,然后使用多个查询来加载其他数据,如果发现用户级别是给定值,但这是一个坏主意,因为它将导致n + 1个查询admins / mods / banned用户,这是一次非常昂贵的数据库之旅。我该怎么办?请帮忙。

2 个答案:

答案 0 :(得分:1)

如果要使用一个查询查询所有usertypes,则必须包含结果表中所有表的列,其中一些表填充null - 值。

要让他们填充数据,请使用左连接,如下所示:

SELECT * 
FROM   userdata u 
       LEFT OUTER JOIN admindata a 
                    ON ( u.userid = a.userid 
                         AND u.usertype = 3 ) 
       LEFT OUTER JOIN moddata m 
                    ON ( u.userid = m.userid 
                         AND u.usertype = 2 ) 
       LEFT OUTER JOIN banneddata b 
                    ON ( u.userid = b.userid 
                         AND u.usertype = -1 ) 
WHERE...

您可能会删除usertype条件,因为其中一个连接表中只应该有数据,但您永远不会知道......

然后,您的程序代码将根据usertype选择正确的列。

P.S。:并非select *仅为了简单起见,在实际代码中更好地列出所有列名...

答案 1 :(得分:0)

虽然在您的域类中具有此层次结构是完全正常的,但我建议您更改数据库中的方法。否则你的查询会非常复杂和缓慢。

您可以只使用另一个名为users_additional_info,包含您所有用户类型所需的列的混合。然后就可以了

SELECT * FROM users 
  LEFT JOIN users_additional_info ON users.id = users_additional_info.user_id

在单个简单查询中获取所有信息。信不信由你,这种方法将在你的桌子开始增长或你决定添加其他类型的用户时,将来会给你带来很多麻烦。