我有两个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
可能包含resource_access
行中user_id
相当于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
)
)
现在,它多次返回资源2的id
、name
和group
(比如12次)。有可能的原因吗?我已经尝试了LEFT
和RIGHT
连接,并得到相同的结果。resource
表中有很多记录,但是没有2的id
。在resource_access
中没有重复的行与同一个用户共享资源两次。
使用说明:
SELECT DISTINCT resource.id, resource.name, resource.group
删除重复项。
内部连接在概念上的工作方式是在两个表之间产生一个完整的叉积。对于输入表中的每个对行,这个交叉积包含一行。然后,它保留匹配所有ON
和WHERE
条件的行,并将其作为结果集返回。如果两个表之间有多个匹配的行,您将在结果集中获得多个行。
如果您从两个表中选择列,您将看到它们实际上不是同一行。它们只是具有来自resource
表的相同数据,但来自resource_access
表的数据不同。但是您不会在结果中显示后面的列。使用DISTINCT
合并结果中的所有这些行。
因为您只从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'
);
在此逻辑下,"join"不能进行产品重复。
选择资源的所有权,然后将其与具有访问权限的资源联合。结果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';