从内部返回值存在不带联接的子查询

时间:2018-07-10 06:01:44

标签: sql postgresql

我有以下查询

SELECT * FROM collection
WHERE id = 1 AND (
    privacy = 0
    OR (privacy = 1 AND
        EXISTS (SELECT * FROM collection_member WHERE collection_id = collection.id AND member_id = 1)
    )
)

这很好。但是我也想从SELECT * FROM collection_member WHERE collection_id = collection.id AND member_id = 1输出结果。使用联接实现的最有效方法是什么? (编辑:可能是subquery encapsulation?)

3 个答案:

答案 0 :(得分:2)

这里是将subselect列为一列的版本。

这仍然是联接,但也许更接近您的需求。

SELECT C.* , 
(SELECT MAX(M.MyColumn) 
 FROM collection_member M
 WHERE collection_id = C.id 
 AND M.member_id = 1
 ) MyColumn
FROM collection C
WHERE C.id = 1 
AND (
    C.privacy = 0
    OR (privacy = 1 AND
        EXISTS (
        SELECT * FROM collection_member CM
        WHERE CM.collection_id = C.id AND CM.member_id = 1)
    )
)

这种方法相对于执行JOIN的唯一好处是,确保不加入多对多和重复计算会更容易一些。

上面显示的查询使用MAX以确保仅返回一行。这可能是您想要的行,也可能不是。

答案 1 :(得分:1)

您无法“从exists子查询中获取值”。

您必须加入:

SELECT *
FROM collection
LEFT JOIN collection_member ON privacy = 0
  OR (privacy = 1
      AND collection_id = collection.id
      AND member_id = 1
  )
WHERE id = 1

当然,与您的查询不同,collection行将在collection_member中的每个匹配行中出现一次。您可以通过汇总所有collection_member值来解决此问题。

答案 2 :(得分:0)

尝试一下

SELECT c.*, cm.*
FROM collection c
        Left Join collection_member cm on (cm.collection_id = c.collection.id and cm.member_id = 1)
WHERE case
        when c.privacy = 0 Then 1
        when c.privacy = 1 and cm.collection_id is not null Then 1
        else 0
      end = 1
and c.id = 1