У нас есть таблица «PROCESS» с первичным ключом process_id. Процессы имеют «элементы», которые хранятся в другой таблице «ПУНКТ» с (process_id, item_id) в качестве первичного ключа. Каждый элемент имеет «события», которые хранятся в еще одной таблице «СОБЫТИЕ» с (process_id, item_id, event_id) в качестве первичного ключа. Событие имеет тип (хранится в столбцах «события». «Event_type») Предположим, что есть события с типом «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
Это подсчет количества элементов для процесса и проверяет, что количество требуемых событий для процесса равно это количество элементов.
Этот запрос трудно читать, трудно понять и не выглядит эффективным.
Есть ли более простые запросы (с точки зрения чтения или с точки зрения производительности) для этой задачи?
Я буду в порядке с запросами, специфичными для оракула, запросы агностики базы данных также приветствуются.
Примеры
процесса
|process_id|
|1 |
|2 |
|3 |
|4 |
товара (пункт всегда принадлежит только одному процессу)
|process_id|item_id|
|1 |11 |
|1 |12 |
|1 |13 |
|2 |14 |
|2 |15 |
|3 |16 |
Event (событие всегда принадлежат только к одному пункту)
|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 должен быть отфильтрован, так как он не имеет событие типа A для элемента 12. Он имеет два события типа A для элемента 11, но они должны рассматриваться как «элемент 11 имеет событие А». process_id = 2 должен возвращаться в результирующем наборе, поскольку он имеет события типа A для всех его элементов. Он имеет два события типа A для пункта 14, и это не должно влиять на результат. process_id = 3 не должен возвращаться, потому что он не имеет каких-либо событий (=> не имеет события типа A для каждого из его элементов) process_id = 4 не должен возвращаться, потому что у него нет никаких элементов (угол кейс).
Выборочные данные и желаемые результаты помогут объяснить то, что вы пытаетесь сделать. –