在没有子查询

时间:2017-12-13 23:12:20

标签: mysql sql

这是SQL fiddle

我有一个包含名单的表格。我想获得一个列表,其中列出了在具有特定状态('S')的相关表中没有条目的所有名称,或者在第3表(与第二个表相关)中具有满足特定状态的字段('A' “)。

我已经能够使用SQL小提琴及其下方显示的子查询来完成此操作,但如果可能的话,我想在没有子查询的情况下执行此操作。

SELECT * FROM name_table LEFT JOIN 
  (SELECT b.name_id FROM b LEFT JOIN c ON (b.c_id = c.id) WHERE (c.c_status = 'A') OR (b.b_status='S'))
 results ON (name_table.id=results.name_id)
WHERE results.name_id IS NULL;

在我的例子中,我喜欢“泰德安德鲁斯”和“杰克约翰逊”行

“John Doe”未包括在内,因为表C的行为“A” “Bill Smith”不包括在内,因为表B的状态为“S” 不包括“Jim Scott”,因为表C有一行状态为“A”(即使表C中有另一行没有状态“A”)

 SELECT * FROM name_table 
  LEFT JOIN b ON (name_table.id = b.name_id)
 LEFT JOIN c ON (b.c_id = c.id) AND (c_status = 'A');
  WHERE (b.b_status IS NULL) OR ((b.b_status <> 'S') AND (c.id IS NULL));

是一次错误地包含“Jim Scott”的尝试

5 个答案:

答案 0 :(得分:2)

我会这样做(sqlfiddle):

  SELECT nt.first, nt.last
    FROM name_table nt
         LEFT JOIN b ON nt.id  = b.name_id
         LEFT JOIN c ON nt.id  = c.a_id
GROUP BY first, last
  HAVING SUM(IF(b.b_status = 'S',1,0)) = 0
     AND SUM(IF(c.c_status = 'A',1,0)) = 0;

有位只计算状态符号的实例,这些符号将人们从您想要的结果集中排除,并且不需要任何人。

答案 1 :(得分:1)

SELECT name_table.id, min(first) as first, min(last) as last
FROM name_table
   LEFT JOIN b ON name_table.id = b.name_id
   LEFT JOIN c ON b.c_id = c.id
GROUP BY name_table.id
HAVING
        count(case when b.b_status = 'S' then 1 end) = 0
    and count(case when c.c_status = 'A' then 1 end) = 0;

由于您要求必须查看c中的多行以确定您是否匹配,您会发现自己正在使用某种聚合。我个人认为这个问题并不是那么可怕。

答案 2 :(得分:0)

即使你说吉姆斯科特不应该被包括在内,但在我看来他并没有像以前的那样。或者是&#39; A的c_status。这是你正在寻找的吗?

select * from name_table
join b on name_table.id = b.name_id and b.b_status <> 'S'
join c on b.c_id = c.id and c.c_status <> 'A';

答案 3 :(得分:0)

这是一种不使用子查询的方法,尽管我想要针对大型数据集检查这种性能:

SELECT a.*
FROM name_table AS a
LEFT JOIN b ON a.id = b.name_id
LEFT JOIN c ON b.c_id = c.id
GROUP BY a.id
HAVING MIN((b.b_status IS NULL OR b.b_status <> 'S') AND (c.c_status IS NULL OR c.c_status <> 'A'));

每行的HAVING子句的计算结果为0或1,表明它是否符合您的条件,然后在所有名称中取最小值,以确保排除Jim Scott - 仅列出所有连接行的名称符合您的标准。

答案 4 :(得分:0)

not exists在这些情况下很有用

select
      *
from name_table t
where not exists (select null from B
                  where t.id = b.name_id and b.b_status = 'S')
and not exists (select null from C
                where t.id = c.a_id and c.c_status = 'A')

<强> Result from Demo

| id | first |     last |
|----|-------|----------|
|  3 |   Ted | Anderson |
|  5 |  Jack |  Johnson |