选择与加入

时间:2015-11-04 23:01:29

标签: sql postgresql

我的表格看起来像这样

Table 1               Table 2
Users                 Options  

id name               id     user_id   option   
-------               ---   --------   --------
1  Donald             1     1          access1
2  John               2     1          access2
3  Bruce              3     1          access3
4  Paul               4     2          access1
5  Ronald             5     2          access3
6  Steve              6     3          access1

现在,我想选择加入这些,以找到只有 access1 的用户 如果我做了类似

的事情
select t1.id,t1.name,t2.id,t2.user_id,t2.option 
from table1 t1, table2 t2 
where t1.id=t2.user_id
and option='access1';

这并没有给我独特的结果,因为在我只需要 user_id = 3 的示例中,我的数据有数百个这样的

我也试过像

这样的东西
select user_id from table2 where option='access1'
and user_id not in (select user_id from table2 where option<>'access1')

还有其他不成功的尝试,但我被困在这里

4 个答案:

答案 0 :(得分:2)

您可以使用EXISTS子查询(技术上,左半连接)来执行此操作:

SELECT  id, name
FROM    table1
WHERE EXISTS(
    SELECT * FROM table2
    WHERE   table1.id = table2.user_id
      AND   table2.option = 'access1'
)

如果您只想要具有access1而不是任何其他访问权限的用户,请添加NOT EXISTS(左侧反半连接;这是一个让您的同事留下深刻印象的术语!):

AND NOT EXISTS (
    SELECT * FROM table2
    WHERE   table1.id = table2.user_id
      AND   table2.option <> 'access1'
)

答案 1 :(得分:1)

bool_and简化了

with users (id,name) as ( values
    (1,'donald'),
    (2,'john'),
    (3,'bruce'),
    (4,'paul'),
    (5,'ronald'),
    (6,'steve')
), options (id,user_id,option) as ( values
    (1,1,'access1'),
    (2,1,'access2'),
    (3,1,'access3'),
    (4,2,'access1'),
    (5,2,'access3'),
    (6,3,'access1')
)
select u.id, u.name
from
    users u
    inner join
    options o on o.user_id = u.id
group by 1, 2
having bool_and(o.option = 'access1')
;
 id | name  
----+-------
  3 | bruce

答案 2 :(得分:0)

如果您想要只有access1的用户,我会使用聚合:

select user_id
from table2
group by user_id
having min(option) = max(option) and min(option) = 'access1';

答案 3 :(得分:0)

WITH users(id,name) AS ( VALUES
  (1,'Donald'),
  (2,'John'),
  (3,'Bruce'),
  (4,'Paul'),
  (5,'Ronald'),
  (6,'Steve')
), options(id,user_id,option) AS ( VALUES
  (1,1,'access1'),
  (2,1,'access2'),
  (3,1,'access3'),
  (4,2,'access1'),
  (5,2,'access3'),
  (6,3,'access1')
), user_access_count AS (
  SELECT op.user_id,count(op.option) AS access_count
  FROM options op
  WHERE EXISTS(
    SELECT 1 FROM options
    WHERE option = 'access1'
  )
  GROUP BY op.user_id
)
SELECT u.id,u.name
FROM users u
INNER JOIN user_access_count uac ON uac.user_id = u.id
WHERE uac.access_count = 1;