这是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”的尝试
答案 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 |