2014-06-29 29 views
2

的倍数,我有两个MySQL表如下:MySQL的内部连接返回同一行

resource 
----------------------------------------------- 
id name   group owner_id 
----------------------------------------------- 
1 MyResource1 hs  11 
2 MyResource2 ms  24 
3 MyResource3 ps  11 
... 

resource_access 
----------------------------------------------- 
id resource_id user_id 
----------------------------------------------- 
1 1    12 
2 2    24 
3 2    11 
4 3    15 
... 

现在,第一台是资源列表,当然,和在owner_id列其各自所有者。第二个表格是与另一个用户“共享”该资源的结果。表resource_access可能包含user_id的记录,该记录相当于resource_access的一行中的owner_id,这是由所有者交换所造成的混乱清理造成的。

我只想获取用户有权访问的任何资源的ID,名称和组,无论它们是所有者还是与它们共享。这里是我的MySQL查询为例用户(24):

SELECT resource.id, resource.name, resource.group 
FROM `resource` 
INNER JOIN resource_access ON (
    resource.owner_id='24' 
    OR (
     resource_access.user_id='24' AND 
     resource_access.resource_id=resource.id 
    ) 
) 

眼下,它返回idname,并group资源2号多次(如十二)个。这有没有可能的原因?我试过LEFTRIGHT连接,我得到了相同的结果。 resource表中有许多记录,但没有任何记录,其中id为2.在resource_access中没有重复的行与同一个用户共享两次资源。

在此先感谢。

+1

使用'SELECT DISTINCT'删除重复项。否则,你会为每个与他们共享的用户获得一行,因为'JOIN'在两个表之间执行交叉产品。 – Barmar

回答

5

用途:

SELECT DISTINCT resource.id, resource.name, resource.group 

删除重复。

内连接在概念上的工作方式是它在两个表之间产生完整的交叉积。该交叉产品包含输入表中各行的每个的一行。然后它保留匹配所有ONWHERE条件的行,并将其作为结果集返回。如果两个表格之间有多个匹配的行,则结果集中会出现多行。

如果您从两个表中选择列,您会发现它们实际上不是同一行。他们只有resource表中的数据相同,但是表resource_access的数据不同。但是你不会在结果中显示后面的列。使用DISTINCT将所有这些行合并到结果中。

+0

是的,我在上面的评论中说过为什么。 – Barmar

+1

假设您还在'SELECT'子句中从'resource_access'返回了数据。然后你会看到行不是重复的,因为它们在这些其他列中是不同的。你只是没有返回这些列,所以你没有看到它们是不同的行。 – Barmar

1

因为你只从resource表中选择,我建议把条件where子句中,而不是使用一个明确的join

SELECT r.id, r.name, r.group 
FROM `resource` r 
WHERE r.owner_id='24' or 
     EXISTS (select 1 
       from resource_access ra 
       where ra.resource_id = r.id and 
        ra.user_id = '24' 
      ); 

有了这个逻辑,“加入”不能产品重复。

+0

你有一个额外的'ON'行。 – Barmar

+0

@Barmar。 。 。谢谢。 –

0

选择资源的所有权,然后将其与具有访问权的资源联合。 产生的user_id列与您的WHERE RA.user_id value不同仅仅意味着资源已分配给它们,而不是拥有资源。希望这可以帮助。

SELECT resource.name,resource.group,resource.owner_id AS user_id 
    FROM resource 
    WHERE resource.owner_id = '11' 

UNION 

SELECT R.name,R.group,R.owner_id AS user_id 
    FROM resource_access RA 
    LEFT JOIN resource R 
    ON (R.id=RA.resource_id) 
    WHERE RA.user_id = '11';