MySQL - 3个表,这个复杂的连接是否可能?

时间:2013-04-22 00:24:52

标签: mysql join

我有三个表:用户,组和关系。

  • 表用户的字段为:usrID,usrName,usrPass,usrPts
  • 包含字段的表组:grpID,grpName,grpMinPts
  • 与字段的表关系:uID,gID

用户可以通过两种方式进行分组:

  • 如果收集组最小分数(users.usrPts> group.grpMinPts ORDER BY group.grpMinPts DSC LIMIT 1)
  • 如果他的关系是在关系表中手动添加的(用户ID作为uID提供,以及作为表名为关系的gID提供的组ID)

我可以创建一个查询,以确定每个用户(或一个特定的),他所属的组,但是,手动关系(使用关系表)应该具有比usrPts更高的优先级grpMinPts?另外,我不想让一个用户显示两次(按点显示他的真实组,但也是相关组)...

提前致谢! :)我试过了:

SELECT * FROM users LEFT JOIN (relation LEFT JOIN groups ON (relation.gID = groups.grpID) ON users.usrID = relation.uID

使用这个我设法提取指定的关系(来自关系表),但是,我不知道如何包含用户点,尊重上述优先级(首先指定)。我知道如何在php中进行一些单独的查询,这很简单,但我很好奇,可以使用一个查询来完成吗?

编辑添加:

感谢使用提供coalesce @GordonLinoff的真正教育技术,我设法使此查询按预期工作。所以,在这里:

SELECT o.usrID, o.usrName, o.usrPass, o.usrPts, t.grpID, t.grpName
FROM (
    SELECT u.*, COALESCE(relationgroupid,groupid) AS thegroupid
        FROM (
        SELECT u.*, (
            SELECT grpID
            FROM groups g
            WHERE u.usrPts > g.grpMinPts
            ORDER BY g.grpMinPts DESC 
            LIMIT 1
        ) AS groupid, (
            SELECT grpUID
            FROM relation r
            WHERE r.userUID = u.usrID
        ) AS relationgroupid
        FROM users u
    )u
)o
JOIN groups t ON t.grpID = o.thegroupid

另外,如果你像我一样想知道这种方法比在PHP中进行三次查询和处理更快或更慢,答案是这种方法稍微快一些。此查询执行和在网页上显示结果的平均时间为14毫秒。三个简单的查询,在PHP中处理和在网页上显示结果需要21毫秒。平均值基于10个案例,平均执行时间实际上是一个恒定的时间。

2 个答案:

答案 0 :(得分:3)

这是一种使用相关子查询来获取每个值的方法。然后使用优先规则选择适当的规则,如果relations存在,则使用该规则,否则使用groups表中的那个:

select u.*,
       coalesce(relationgroupid, groupid) as thegroupid
from (select u.*,
             (select grpid from groups g where u.usrPts > g.grpMinPts order by g.grpMinPts desc limit 1
             ) as groupid,
             (select gid from relations r where r.userId = u.userId
             ) as relationgroupid
      from users u
    ) u

答案 1 :(得分:0)

尝试这样的事情

select user.name, group.name
from group
join relation on relation.gid = group.gid
join user on user.uid = relation.uid
union
select user.name, g1.name
from group g1
join group g2 on g2.minpts > g1.minpts
join user on user.pts between g1.minpts and g2.minpts