Sql 从满足子表中至少有一条记录的所有行的条件的表中选择行
我们有一个带有进程id主键的表“进程”。 流程有“项”,它们存储在另一个表“项”中,主键为(流程id,项目id)。 每个项目都有“事件”,它们存储在另一个表“事件”中,其中(进程id、项目id、事件id)作为主键。事件具有类型(存储在“事件”“事件类型”列中) 假设存在类型为“A”的事件 我想为所有项目选择至少有一个“A”类型事件的流程(因此,如果一个项目没有此类事件,我不需要在结果集中使用此类流程) 我最后提出了以下问题:Sql 从满足子表中至少有一条记录的所有行的条件的表中选择行,sql,oracle,group-by,aggregate-functions,having,Sql,Oracle,Group By,Aggregate Functions,Having,我们有一个带有进程id主键的表“进程”。 流程有“项”,它们存储在另一个表“项”中,主键为(流程id,项目id)。 每个项目都有“事件”,它们存储在另一个表“事件”中,其中(进程id、项目id、事件id)作为主键。事件具有类型(存储在“事件”“事件类型”列中) 假设存在类型为“A”的事件 我想为所有项目选择至少有一个“A”类型事件的流程(因此,如果一个项目没有此类事件,我不需要在结果集中使用此类流程) 我最后提出了以下问题: SELECT needed_processes.process_id
SELECT needed_processes.process_id FROM (
SELECT items.process_id, items.number_of_items, events.number_of_events FROM
(SELECT process.process_id, count(*) number_of_items FROM process
JOIN item ON process.process_id = item.process_id
GROUP BY process.process_id
) items JOIN
(SELECT needed_events.process_id, count(*) number_of_events FROM
(SELECT process.process_id, item.item_id FROM process JOIN item
ON process.process_id = item.process_id JOIN events ON item.process_id = event.process_id
AND item.item_id = event.item_id
WHERE event.event_type = 'A'
group by process.process_id, item.item_id
) needed_events group by needed_events.process_id
) events ON items.process_id = events.process_id
where items.number_of_items = events.number_of_events) needed_processes
它计算流程的项目数,并检查流程所需事件数是否等于其项目数
这个查询很难阅读,也很难理解,而且看起来效率不高
此任务是否有更简单的查询(在阅读或性能方面)
我可以使用oracle特定的查询,也欢迎使用与数据库无关的查询
示例
过程
|process_id|
|1 |
|2 |
|3 |
|4 |
项目(项目始终只属于一个流程)
事件(事件始终只属于一个项目)
结果
|process_id|
|2 |
应过滤掉进程_id=1,因为它没有项目12的A类型事件。项目11有两个A类事件,但应将其视为“项目11有事件A”。
进程_id=2应该在结果集中返回,因为它的所有项目都有A类型的事件。项目14有两个A类事件,这不应影响结果。
不应返回进程_id=3,因为它没有任何事件(=>没有针对其每个项的类型为A的事件)
不应返回process_id=4,因为它没有任何项目(角落案例)。这将返回每个项目都有事件“A”的所有流程:
样本数据和期望的结果将有助于解释您正在尝试做什么。谢谢,这是非常棒的,可以很容易地理解和工作良好!
|process_id|item_id|event_id|event_type|
|1 |11 |21 |A |
|1 |11 |22 |A |
|1 |11 |23 |B |
|1 |13 |24 |A |
|2 |14 |25 |A |
|2 |14 |26 |A |
|2 |15 |27 |A |
|2 |15 |28 |B |
|process_id|
|2 |
select process_id
from events
group by process_id
having count(distinct item_id) -- all items
= count(distinct case when event_type = 'A' then item_id end) -- only items with event 'A'