SQL - 检查表中是否存在列表中的值并相应地返回布尔值

时间:2017-08-30 11:53:12

标签: sql postgresql relational-division

我有一个由3个表组成的简单数据库模式

用户
ID
命名
matricule

文档
ID
序列

User_Document (加入表)
USER_ID
document_id

我想检查连接表(User_Document)中是否存在列表的所有项目(Document.serial列表),然后返回true 如果至少有一个不存在,则应返回false

有我当前的查询

SELECT CASE WHEN EXISTS (
SELECT *
FROM user_document ud
INNER JOIN  document d ON d.id= ud.document_id  
INNER JOIN  user u ON u.id = ud.user_id
where u.matricule='123'
and d.serial in ('#1' ,'#2' , '#3')
)
THEN TRUE 
ELSE FALSE 
END

这不起作用,因为即使连接表中不存在单个列表项,它也会一直返回

我在PostgreSQL下

非常感谢

3 个答案:

答案 0 :(得分:2)

SELECT
D.*,
(CASE WHEN (SELECT 1 FROM USER_DOCUMENT 
WHERE D.ID = UD.DOCUMENT_ID LIMIT 1) = 1 THEN TRUE ELSE FALSE END)
FROM DOCUMENT D

答案 1 :(得分:2)

试试这个:

     SELECT bool_and(ud.document_id is not null) as all_match,
            bool_or(ud.documnet_id is not null) as at_least_one_matches
       FROM document d
  LEFT JOIN user_document ud ON d.id = ud.document_id;

这应该通过,执行左连接,如果 all 匹配则返回true,如果一个不匹配则返回false。如果至少有一个匹配,则第二个返回true。

如果你想笑

答案 2 :(得分:1)

在数组中聚合连续符并与所需连续符的数组进行比较:

SELECT ARRAY(SELECT d.serial
             FROM user_document ud
             JOIN document d ON d.id = ud.document_id  
             JOIN "user" u ON u.id = ud.user_id
             WHERE u.matricule = '123') @> ARRAY['#1', '#2', '#3']::varchar[];

请注意,我必须在查询中引用user的表名,因为它是PostgreSQL中的reserved key word和SQL标准。

另一种方法是计算与列表匹配的不同序列号,并检查计数是否与列表的长度匹配:

SELECT count(DISTINCT d.serial) = 3
FROM user_document ud
JOIN document d ON d.id= ud.document_id  
JOIN "user" u ON u.id = ud.user_id
WHERE u.matricule='123' AND d.serial IN ('#1','#2','#3');

此版本也适用于不支持数组的数据库(例如MySQL),如果有大量与用户相关的文档,则可能更有效。