来自 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'
我们有 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'