从满足子表中所有行的条件的表中选择行,这些行在另一个表

时间:2015-09-20 11:33:10

标签: sql oracle group-by aggregate-functions having

我们有process_id主键的表“PROCESS”。 进程具有“项目”,其存储在具有(process_id,item_id)作为主键的另一个表“ITEM”中。 每个项目都有“事件”,这些事件存储在另一个表“EVENT”中,其中(process_id,item_id,event_id)作为主键。事件有类型(存储在“events”。“event_type”列中) 假设存在类型为“A”的事件。

我想选择所有项目中至少有一个类型为“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的事件,但它们应该被视为“项目11具有事件A”。 process_id = 2应该在结果集中返回,因为它的所有项都有类型A的事件。对于项目14,它有两个类型A的事件,这不应该影响结果。 不应返回process_id = 3,因为它没有任何事件(=>每个项目都没有类型A的事件) 不应返回process_id = 4,因为它没有任何项目(角落案例)。

1 个答案:

答案 0 :(得分:1)

这将返回每个项目的事件'A'的所有进程:

.captionHover::before {
    background: rgba(248, 214, 215, .5);
}