来自 table 的 Select 行满足子 table 中所有行的条件,在另一个 table 中至少有一个记录

Select rows from a table satisfying criteria for all rows in a child table which have at least one record in another table

我们有 table "PROCESS" 和 process_id 主键。 进程有 "items" 存储在另一个 table "ITEM" 中,以 (process_id, item_id) 作为主键。 每个项目都有 "events" 存储在另一个 table "EVENT" 中,以 (process_id, item_id, event_id) 作为主键。事件有类型(存储在 "events"."event_type" 列中) 假设有 "A".

类型的事件

我想要 select 进程,其所有项目至少有一个 "A" 类型的事件(因此,如果一个项目没有这样的事件,我不需要这样的结果集中的过程)。

我得到了以下查询:

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|item_id|
|1         |11     |
|1         |12     |
|1         |13     |
|2         |14     |
|2         |15     |
|3         |16     |

事件(事件总是只属于一项)

|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         |

process_id=1 应该被过滤掉,因为它没有项目 12 的 A 类型事件。它有两个项目 11 的 A 类型事件,但它们应该被视为 "item 11 has event A". process_id=2 应该在结果集中返回,因为它的所有项目都有类型 A 的事件。对于第 14 项,它有两个 A 类事件,这应该不会影响结果。 process_id=3 不应该被返回,因为它没有任何事件(=> 它的每个项目都没有类型 A 的事件) process_id=4 不应返回,因为它没有任何项目(极端情况)。

此 returns 所有进程中 每个 项的事件 'A':

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'