mysql,如何选择没有节点的树

时间:2014-04-17 08:50:30

标签: mysql sql

我确定这是一项简单的任务,但我被困了几天:我已经简化了表格:

INSERT INTO `tree` (`fruit`, `tree`) VALUES
('apple',   'A'),
('pear',    'A'),
('apple',   'B'),
('banana',  'B');

例如,我需要准确说明我需要的水果和我不需要的水果,所以我喜欢这样的东西:

IN ('apple', 'banana') && NOT IN('pear')

应该返回" B"因为我们有苹果和香蕉的树,没有梨

有什么想法吗?谢谢。

4 个答案:

答案 0 :(得分:2)

简单的选择应该使用NOT EXISTS检查。

SELECT t1.tree FROM tree t1 WHERE t1.fruit='apple' 
AND NOT EXISTS 
           (SELECT 1 
            FROM tree t2 
             WHERE t1.tree=t2.tree and t2.fruit='pear');

答案 1 :(得分:2)

如果您只想在样本中使用“B”:

select t.fruit, t.tree
from tree t
where t.fruit = 'apple'
and not exists (select null
                  from tree t1
                  where t1.tree = t.tree
                  and t.fruit = 'pear');

所以,如果你有

INSERT INTO `tree` (`fruit`, `tree`) VALUES
('apple',   'A'),
('pear',    'A'),
('apple',   'B')
('banana', 'B')

您只会获得第apple-B

如果你想扩展你的样本,并获得所有至少有一次苹果,没有梨,还有香蕉的树木,例如

select t.fruit, t.tree
from tree t
where not exists (select null
                      from tree t1
                      where t1.tree = t.tree
                      and t.fruit = 'pear')
and exists        (select null
                      from tree t1
                      where t1.tree = t.tree
                      and t.fruit = 'apple');

然后您将获得apple-Bbanana-B

答案 2 :(得分:2)

虽然早期的答案是完全正确的,但我认为你可以使用LEFT JOIN尝试没有嵌套SQL的SQL

SELECT A.tree FROM
    tree A LEFT JOIN tree B
ON
    A.tree = B.tree AND
    B.fruit = 'pear' 
WHERE 
    B.fruit IS NULL AND
    A.fruit = 'apple';

ON条件将使tree表内笛卡尔积的任何组合的所有B. *字段为NULL,其中'树'列不匹配或第二个水果不是梨。 WHERE条件将过滤结果以仅包含第二组为空且其果实为apple的树。

结合两种条件:所有那些带苹果而没有梨的树木。

编辑:(在您的问题编辑后)

每当你没有重复的树 - 果对时,你可以尝试:

SELECT A.tree FROM
    tree A LEFT JOIN tree B
ON
    A.tree = B.tree AND
    B.fruit IN ('pear') #Can't have
WHERE 
    B.fruit IS NULL AND
    A.fruit IN ('apple','banana') # Must have           <---\
GROUP BY A.tree HAVING COUNT(1) = 2; #Number of elements in /

答案 3 :(得分:1)

您还可以在HAVING子句中使用分组和检查聚合值,如下所示:

SELECT   tree
FROM     tree
GROUP BY tree
HAVING   MAX(fruit IN ('apple', 'banana')) = 1
   AND   MAX(fruit IN ('pear')           ) = 0
;

同一方法的更独立于平台的版本将涉及CASE:

SELECT   tree
FROM     tree
GROUP BY tree
HAVING   MAX(CASE WHEN fruit IN ('apple', 'banana') THEN 1 ELSE 0 END) = 1
   AND   MAX(CASE WHEN fruit IN ('pear')            THEN 1 ELSE 0 END) = 0
;

要指定树必须同时包含applebanana,请再添加一个条件:

AND COUNT(*) = 2

如果允许树具有重复的水果条目,请改为使用此条件:

AND COUNT(DISTINCT fruit) = 2

或者,您可以为每个允许的水果指定单独的条件,如下所示:

SELECT   tree
FROM     tree
GROUP BY tree
HAVING   MAX(fruit = 'apple'  ) = 1
   AND   MAX(fruit = 'banana' ) = 1
   AND   MAX(fruit IN ('pear')) = 0
;