SQL subselect 基于多个子行的过滤
SQL subselect filtering based on multiple sub-rows
我有两个表,想根据第二个表的 'child' 数据从第一个表中提取某些列。
- 我正在使用 SQL Anywhere 12
Table 1)
让我们称之为 Projects
proj_id | Name
--------+---------
10 | Proj_1
20 | Proj_2
30 | Proj_3
40 | Proj_4
Table 2)
让我们称之为 tasks
proj_id | task_id | Status
--------+---------+-----------
10 | 1 | Ready
10 | 2 | Cancelled
10 | 3 | Ready
20 | 1 | Complete
20 | 2 | Ready
30 | 1 | Ready
30 | 2 | Not Ready
30 | 3 | Complete
40 | 1 | Ready
40 | 2 | Ready
我想做的是找出哪些'projects'有'tasks'是'ready'.
这里棘手的部分是,如果其他 任务 是 完成 就没问题,但如果它们不是完成 或 准备就绪
所以换句话说输出应该是这样的:
Name | Status
-------+--------
Proj_2 | Ready
Proj_4 | Ready
我不想在结果集中看到Proj_1(任务是已取消)或Proj_3(任务未准备好)
我不会发布任何 SQL,因为我不确定这是否可能....
通常我会在 C++ 中用 2 个多语句执行类似的操作,但在这种情况下我需要在单个语句中执行此操作,因为我需要将数据传递给第三方打印程序。
NOT EXISTS
解决方案,即 return 一个项目,如果它有一个就绪任务,并且除了就绪和完成之外没有其他任务:
select p.*
from Projects p
join tasks t on p.proj_id = t.proj_id
where t.Status = 'ready'
and not exists (select * from tasks t2
where t2.proj_id = t.proj_id
and t2.Status NOT IN ('ready', 'Complete'))
有多种方法可以处理此类查询。我喜欢将聚合与 having
子句一起使用,因为它非常灵活并且所有逻辑都在 having
子句中:
select t.proj_id
from tasks t
group by t.proj_id
having sum(case when status = 'ready' then 1 else 0 end) > 0 and
sum(case when status not in ('complete, 'ready') then 1 else 0 end) = 0;
having
子句中的每个条件都会计算具有特定条件的任务数。第一个计算就绪任务的数量,> 0
表示至少有一个。第二个统计non-ready、non-complete的个数。 = 0
表示有 none.
我有两个表,想根据第二个表的 'child' 数据从第一个表中提取某些列。
- 我正在使用 SQL Anywhere 12
Table 1) 让我们称之为 Projects
proj_id | Name --------+--------- 10 | Proj_1 20 | Proj_2 30 | Proj_3 40 | Proj_4
Table 2) 让我们称之为 tasks
proj_id | task_id | Status --------+---------+----------- 10 | 1 | Ready 10 | 2 | Cancelled 10 | 3 | Ready 20 | 1 | Complete 20 | 2 | Ready 30 | 1 | Ready 30 | 2 | Not Ready 30 | 3 | Complete 40 | 1 | Ready 40 | 2 | Ready
我想做的是找出哪些'projects'有'tasks'是'ready'.
这里棘手的部分是,如果其他 任务 是 完成 就没问题,但如果它们不是完成 或 准备就绪
所以换句话说输出应该是这样的:
Name | Status -------+-------- Proj_2 | Ready Proj_4 | Ready
我不想在结果集中看到Proj_1(任务是已取消)或Proj_3(任务未准备好)
我不会发布任何 SQL,因为我不确定这是否可能....
通常我会在 C++ 中用 2 个多语句执行类似的操作,但在这种情况下我需要在单个语句中执行此操作,因为我需要将数据传递给第三方打印程序。
NOT EXISTS
解决方案,即 return 一个项目,如果它有一个就绪任务,并且除了就绪和完成之外没有其他任务:
select p.*
from Projects p
join tasks t on p.proj_id = t.proj_id
where t.Status = 'ready'
and not exists (select * from tasks t2
where t2.proj_id = t.proj_id
and t2.Status NOT IN ('ready', 'Complete'))
有多种方法可以处理此类查询。我喜欢将聚合与 having
子句一起使用,因为它非常灵活并且所有逻辑都在 having
子句中:
select t.proj_id
from tasks t
group by t.proj_id
having sum(case when status = 'ready' then 1 else 0 end) > 0 and
sum(case when status not in ('complete, 'ready') then 1 else 0 end) = 0;
having
子句中的每个条件都会计算具有特定条件的任务数。第一个计算就绪任务的数量,> 0
表示至少有一个。第二个统计non-ready、non-complete的个数。 = 0
表示有 none.