Сращивание подзапросов разных типов
Для сращивание двух конъюнктивных подзапросов, удовлетворяющих свойству включения и имеющих разные типы, требуется применение другого метода. Рассмотрим запрос Q4, который является несколько упрощенным вариантом запроса 21 из TPC-H.
Q4
SELECT s_name FROM supplier, lineitem L1 WHERE s_suppkey = l_suppkey AND EXISTS (SELECT * FROM lineitem L2 WHERE l_orderkey = L1.l_orderkey AND l_suppkey <> L1.l_suppkey) AND NOT EXISTS (SELECT * FROM lineitem L3 WHERE l_orderkey = L1.l_orderkey AND l_suppkey <> L1.l_suppkey AND l_receiptdate > l_commitdate);
Два подзапроса в Q4 отличаются только своими типами и тем, что в подзапросе с NOT EXISTS имеется дополнительный предикат фильтрации l_receipt_date > l_commitdate. Сращивание подзапросов приводит к запросу Q5 с единственным подзапросом с EXISTS, в результате чего устраняется один экземпляр таблицы lineitem.
Q5
SELECT s_name FROM supplier, lineitem L1 WHERE s_suppkey = l_suppkey AND EXISTS (SELECT 1 FROM lineitem L2 WHERE l_orderkey = L1.l_orderkey AND l_suppkey <> L1.l_suppkey) HAVING SUM(CASE WHEN l_receiptdate > l_commitdate THEN 1 ELSE 0 END) = 0);
Агрегатная функция раздела HAVING возвращает общее количество строк, удовлетворяющих предикату подзапроса. Раздел HAVING, включенный в срощенный подзапрос, является новым предикатом фильтрации, который проверяет, удовлетворяет ли какая-либо строка предикату подзапроса, тем самым имитируя поведение удаленного подзапроса с NOT EXISTS.
Для каждого набора корреляционных значений подзапросы в Q4 могут находиться в одном из трех состояний:
-
Если подзапрос EXISTS не возвращает строк (т.е. вычисляется в FALSE), то результатом конъюнкции двух подзапросов является FALSE. В Q5 раздел HAVING применяется к пустому множеству, и срощенный подзапрос с EXISTS также вычисляется в FALSE.
-
Если подзапрос с EXISTS
возвращает несколько строк (т.е. вычисляется в TRUE), и подзапрос NOT EXISTS тоже возвращает несколько строк (т.е. вычисляется в FALSE), то результатом конъюнкции двух подзапросов является FALSE. В Q5 раздел HAVING применяется к непустому множеству строк, для которых l_receiptdate > l_commitdate, и потому вычисляется в FALSE; таким образом, срощенный подзапрос вычисляется в FALSE.
-
Если подзапрос с EXISTS
возвращает несколько строк, а подзапрос с NOT EXISTS не возвращает строк из-за дополнительных предикатов фильтрации, то результатом конъюнкции двух подзапросов является TRUE. В Q5 раздел HAVING
применяется к непустому множеству строк, для которых неверно, что l_receiptdate > l_commitdate, и потому вычисляется в TRUE; таким образом, срощенный подзапрос вычисляется в TRUE.
Приведенное обсуждение обосновывает эквивалентность запросов Q4 и Q5. В том случае, когда подзапрос с NOT EXISTS является включающим запросом, а конъюнктивный подзапрос с EXISTS – включаемым запросом, сращивание состоит в удалении обоих подзапросов и замене их предикатом FALSE. Условия, при наличии которых подзапрос с EXISTS возвращает несколько строк (т.е. вычисляется в TRUE), гарантируют, что подзапрос с NOT EXISTS
также вернет несколько строк (т.е. будет вычислен в FALSE). В том случае, когда подзапрос с NOT EXISTS не возвращает строк, подзапрос с EXISTS также не вернет строк. Следовательно, результатом конъюнкции двух подзапросов всегда будет FALSE.
Аналогичная аргументация может быть произведена, и аналогичное сращивание может быть выполнено в том случае, когда имеется дизъюнкции подзапросов с EXISTS и NOT EXISTS, и удовлетворяется свойство включения.