将联接限制为完整集而不是子集

时间:2015-11-18 14:25:30

标签: mysql sql join

我试图获取仅对某些用户可见的帖子的ID列表。我目前的陈述是:

SELECT `p`.`id` 
FROM   `posts` AS `p` 
       INNER JOIN `post_visibilities` AS `pv` 
               ON `pv`.`post_id` = `p`.`id` 
WHERE  `pv`.`user_id` IN ( 1, 2, 3, 4 ); 

这有点奏效,但IN()子句的行为有点像子集,我收到的帖子已被这四个用户其他用户看到了。我需要找到这四个用户可见的帖子。

2 个答案:

答案 0 :(得分:0)

您可以直接翻译并使用不存在的内容。 虽然我不得不说一个不存在(因此一个子查询)总是有点慢。 不确定是否有更快的方法。

SELECT DISTINCT `p`.`id` 
FROM   `posts` AS `p` 
       INNER JOIN `post_visibilities` AS `pv` 
               ON `pv`.`post_id` = `p`.`id` 
WHERE  `pv`.`user_id` IN ( 1, 2, 3, 4 )
       and not exists (select 1 from `post_visibilities` as 'excluder'
         where excluder.post_id = p.id and excluder.user_id not in (1,2,3,4)); 

答案 1 :(得分:0)

使用条件SUM

  • 我认为post_visibilty每个帖子只有ID一次。
  • 如果帖子ID的所有4个post_visibilty都有SUM将为4
  • 如果其他人也有post_visibilty SUM将永远不会是4。

SELECT `p`.`id` 
FROM   `posts` AS `p` 
INNER JOIN `post_visibilities` AS `pv` 
           ON `pv`.`post_id` = `p`.`id` 
GROUP BY `p`.`id` 
HAVING SUM (CASE 
              WHEN `pv`.`user_id` IN ( 1, 2, 3, 4 ) THEN 1
              ELSE -1
            END) = 4;

您的问题的其他解释也可以使用条件SUM

来完成
HAVING 
    SUM (CASE 
           WHEN `pv`.`user_id` IN ( 1, 2, 3, 4 ) THEN 1
           ELSE 0 
         END) >= 1   -- one or more have visibilty
AND SUM (CASE 
           WHEN `pv`.`user_id` NOT IN ( 1, 2, 3, 4 ) THEN 1
           ELSE 0 
         END) = 0   -- no one else have visibilty