假设我与用户和项目之间存在多对多关系:一个用户可能属于多个项目,而一个项目可能具有多个用户。此关系在表中编码user_projects:
user_projects
create table user_projects ( proj_id int references projs(id) not null, user_id int references users(id) not null, primary key (proj_id, user_id) );
这是我的问题:给定一组用户(user1,user2,…),我想选择给定用户集为其所有用户的子集的所有项目。
例如,如果我在下面插入数据,然后询问用户1和2的所有项目,则查询应仅返回项目1。
insert into user_projects values (1, 1); insert into user_projects values (1, 2); insert into user_projects values (1, 3); insert into user_projects values (2, 1); insert into user_projects values (2, 3);
(如果最好的解决方案恰巧是非标准的,那么我使用的是PostgreSQL。)
编辑: 为澄清起见,应将用户集解释为对要返回的项目列表的约束。集合{u1,u2}表示项目列表应仅包括那些至少具有用户u1和u2的项目;集合{u1}表示应返回至少具有用户u1的所有项目,而在有限的情况下,空集合表示应返回 所有 项目。
Select project_ID from user_projects where user_ID in (1,2) group by project_ID Having count(*) = 2
您知道您有2个用户,您知道他们将是唯一的(主键),因此您知道如果有2条记录,那么对于同一项目,则是您想要的。
您的问题表明您收到了GIVEN个用户,因此您知道哪些用户以及有多少用户。上面的SQL可以更新为接受这些已知参数的参数,因此保持动态,而不仅限于2个用户。
where user_ID in (userlist) having count(*) = (cntuserList)
-----------处理用户为空时的情况-----
Select P.project_ID from Projects P LEFT JOIN user_projects UP where (UP.user_ID in (1,2) OR UP.USER_ID is null) group by project_ID Having count(*) = 2
这就是它的作用。它返回所有项目,并且如果有与该项目相关的用户,它将对其进行标识。如果您的集合包含用户,则返回的项目列表将由该集合过滤,以确保整个集合都通过Haveing子句位于项目中。
如果集合为空,则LEFT联接以及userID为null语句将保留未列出用户的项目,无论集合是否为空。hading子句会将集合进一步减少为您在集合中定义的用户数量,或者为0表示返回所有未分配用户的项目。
我们还没有讨论的另一种极端情况是,如果一个项目包含的用户数量超过了您在集合中定义的数量,那么该怎么办。目前将退还该项目;但我不是很肯定那是你想要的。
在旁注感谢您让我思考。我不再需要太多的代码了。这就是为什么我不时在这里拖钓看看我是否可以帮忙!