2014-10-07 58 views
0

我有3个表。在第一个表格中,每个项目都有多个条目。第二个基本上是一个映射表。这比这更复杂,但对于这个例子我简化了。我在表2中检查了一个简单的条件。在第三个表中,每个条目都有一个设置为true或false的标志。我想返回第一个表上第三个表上的所有匹配行都为false的行。在下面的例子中,结果将返回项目A b/c表3中Jane和Fred的所有行都是假的,但是没有其他项目,因为每个其他项目在表3中至少有一个真实条目。sql查询加入其中没有一个满足条件

Project | Client   name | id   id | active 
    ---------------   ----------------  --------------- 
    A  | Jane   John | 1   1 | false 
    A  | Fred   Jane | 2   1 | true 
    B  | Mary   Fred | 3   2 | false 
    B  | Jane   Mary | 4   2 | false 
    C  | John         3 | false 
    C  | Jane         3 | false 
    D  | Jane         4 | true 
    D  | Mary         4 | false 
    D  | John 
    D  | Fred 
+0

您能否根据您的样本数据以表格格式提供结果集? – 2014-10-07 16:05:50

回答

1

以下应该做你想要什么:

select t1.* 
from table1 t1 
where not exists (select 1 
        from table2 t2 join 
         table3 t3 
         on t2.id = t3.id 
        where t2.name = t1.name and t3.active <> false 
       ); 

join之一发生故障时(示例数据中不存在此情况),有什么不明之处。这将返回该行,因为即使在这种情况下,第三个表中的所有匹配行也都是false。

0
SELECT t1.* FROM t1 
INNER JOIN t2 ON t1.Client = t2.name 
WHERE t2.id IN (
SELECT id FROM t3 
GROUP BY id, active 
HAVING SUM(CASE active WHEN false THEN 1 ELSE 0 END) = COUNT(1) 
) 
0

你有两个做选择从第一个表联接和一个简单的WHERE条件:

SELECT 
    res.Project 
FROM 
    (SELECT 
     table1.Project, 
     BOOL_OR(res) as active 
    FROM 
     table1 
     JOIN table2 ON table2.name=table1.Client 
     JOIN table3 ON table3.id=table2.id 
    GROUP BY table1.Project 
    ) as res 
WHERE 
    res.active=FALSE 
+0

这将返回所有存在假标志的地方,即使还有一个真标志。 – RememberME 2014-10-07 16:14:14

+0

编辑我的答案。以前的SQL像“active”字段的子查询分组一样使用。 – dmikam 2014-10-08 07:53:29

0

一个相当直接的加入与HAVING应该给你你想要的结果;

SELECT t1.project, t1.client 
FROM table1 t1 
JOIN table2 t2 ON t1.client = t2.name 
JOIN table3 t3 ON t2.id = t3.id 
GROUP BY t1.project, t1.client 
HAVING NOT MAX(t3.active) 

An SQLfiddle to test with

这基本上只是直接连接所有表,按客户端和项目对结果进行分组。然后它使用NOT MAX(t3.active)来检查组中所有布尔值是否为假。

该版本选择不返回没有任何活动标志的客户端/项目进行检查。