如何选择在一个表中(多对多)共存的ID

时间:2018-07-07 02:59:39

标签: sql

我偶然发现了一个我在过去一周试图解决的问题,希望社区能够帮助我解决这个问题。我会尽力解释。

 User Table               Channel Table              Member Table
 id | name                    id                   ch.Id | u.Id
----|----                    -----                 -------------
  1 | george                   1                      1  |  1
  2 | john                     2                      1  |  2
  3 | joe                      3                      2  |  1
  4 | jessie                   4                      2  |  3
                                                      3  |  1
                                                      3  |  3

所以如图所示,我有3张桌子。成员表处理用户表与渠道表之间的关联。我正在尝试做的是仅拉出与一个渠道相关联的用户,而不在查询中识别该渠道。

到目前为止,我至少有一个呈现两个给定用户的概念,但是如下所示的查询将呈现两个用户所包含的每个频道。再次,我想将其进一步并且仅与请求的用户一起拉出一个频道,而不会(如果可能)在查询中提及频道ID

SELECT ch.id as chid, u.id as uid FROM channels AS ch 
  LEFT JOIN members as mem on ch.id = "mem"."channelId" 
  LEFT JOIN users AS u ON u.id = "mem"."userId" WHERE u.id in (1,2);

希望我对此做了清楚的解释。谢谢大家!

4 个答案:

答案 0 :(得分:0)

您可以使用not exists

select m.*
from members m
where not exists (select 1
                  from members m2
                  where m2.u_id = m.u_id and m2.ch_id <> m.ch_id
                 );

答案 1 :(得分:0)

如果我正确理解了您的意图,则下面的SQL代码将为您提供帮助。

SELECT 
    U.*,
    M.*
FROM USER U
INNER JOIN MEMBER M ON (M.U.ID = U.ID)
WHERE U.ID IN (1,2,3,4)
AND M.CH.ID IN (1,2,3,4);

它选择数据而不访问通道表。 但是,结果将带有重复的行,在这种情况下,您可以对所需的字段进行GROUP BY,并且如果需要,可以使用一些与组一起使用的函数来进一步处理数据(组concat函数)。

此外,正如已经指出的,您可以使用EXISTS或NOT EXISTS和子查询。根据应用程序应达到的容量,它可能会成为性能问题。

干杯

答案 2 :(得分:0)

您可以使用GROUP BY子句来标识只有一个频道的用户:

select u_id
from members m
group by u_id
having min(ch_id) <> max(ch_id);

答案 3 :(得分:0)

只有1个频道ID的用户ID?

select max(mem.channelId) as cid, mem.userId as uid
from members as mem
group by mem.userId
having count(distinct mem.channelId) = 1;

如果您担心成员表包含在其他表中已删除的ID?
(如果使用外键来强制参照完整性,则不应该如此)
然后将其他表内部连接到它。

select max(mem.channelId) as cid, mem.userId as uid
from members as mem
join channels as ch on ch.id = mem.channelId 
join users as u on u.id = mem.userId
group by mem.userId
having count(distinct mem.channelId) = 1;

示例代码段:

declare @users table (id int identity(1,1) primary key, name varchar(30));
declare @channels table (id int identity(1,1) primary key, name varchar(30));
declare @members table (ChannelId int, UserId int);
insert into @users (name) values ('george'),('john'),('joe'),('jessie');
insert into @channels (name) values ('one'),('two'),('three'),('four');
insert into @members (channelId, userId) values (1,1),(1,2),(2,1),(2,3),(3,1),(3,3);

select 
 mem.userId as uid, max(mem.channelId) as cid
 , max(u.name) as uname
 , max(ch.name) as cname
from @members as mem
join @channels as ch on ch.id = mem.channelId
join @users as u on u.id = mem.userId
group by mem.userId
having count(distinct mem.channelId) = 1;