FirebirdSQL logo

Коррелированные подзапросы

Подзапрос может быть коррелированным (соотнесённым). Запрос называется коррелированным, когда подзапрос и основной запрос взаимозависимы.Это означает, что для обработки каждой записи подзапроса, должна быть получена также запись из основного запроса, т.е.подзапрос всецело зависит от основного запроса.

Example 1. Коррелированный подзапрос
SELECT *
FROM Customers C
WHERE EXISTS
      (SELECT *
       FROM Orders O
       WHERE C.cnum = O.cnum
         AND O.adate = DATE '10.03.1990');

При использовании подзапросов для получения значений выходного столбца в списке выбора SELECT, подзапрос должен возвращать скалярный результат.

Подзапросы возвращающие скалярный результат

Подзапросы, используемые в предикатах поиска, кроме предикатов существования и количественных предикатов, должны возвращать скалярный результат, то есть не более чем один столбец из одной отобранной строки или одно агрегированное значение, в противном случае, произойдёт ошибка времени выполнения (“Multiple rows in a singleton select…​”).

Note

Несмотря на то, что Firebird сообщает о подлинной ошибке, сообщение может немного вводить в заблуждение.“singleton SELECT” — это запрос, который не должен возвращать более одной строки.Однако “singleton” и “scalar” не являются синонимами: не все одноэлементные SELECTS должны быть скалярными; а выборка по одному столбцу может возвращать несколько строк для предикатов существования и количественных предикатов.

Example 1. Подзапрос в качестве выходного столбца в списке выбора
SELECT
    e.first_name,
    e.last_name,
    (SELECT
         sh.new_salary
     FROM
         salary_history sh
     WHERE
         sh.emp_no = e.emp_no
     ORDER BY sh.change_date DESC ROWS 1) AS last_salary
FROM
    employee e
Example 2. Подзапрос в предложении WHERE для получения значения максимальной зарплаты сотрудника и фильтрации по нему
SELECT
    e.first_name,
    e.last_name,
    e.salary
FROM
    employee e
WHERE
    e.salary = (SELECT
                    MAX(ie.salary)
                FROM
                    employee ie)

Предикаты

Предикат — это простое выражение, утверждающее некоторый факт, назовем его P.Если P разрешается как TRUE, он успешен.Если он принимает значение FALSE или NULL (UNKNOWN), он терпит неудачу.Однако здесь кроется ловушка: предположим, что предикат P возвращает FALSE.В этом случае NOT (P) вернет TRUE.С другой стороны, если P возвращает NULL (неизвестно), то NOT (P) также возвращает NULL.

В SQL предикаты проверяют в ограничении CHECK, предложении WHERE, выражении CASE, условии соединения во фразе ON для предложений JOIN, а также в предложении HAVING.В PSQL операторы управления потоком выполнения проверяют предикаты в предложениях IF, WHILE и WHEN. Поскольку начиная с Firebird 3.0 введена поддержка логического типа, то предикат может встречаться в любом правильном выражении.

Утверждения

Проверяемые условия не всегда являются простыми предикатами.Они могут быть группой предикатов, каждый из которых при вычислении делает вклад в вычислении общей истинности.Такие сложные условия называются утверждениями.Утверждения могут состоять из одного или нескольких предикатов, связанных логическими операторами AND, OR и NOT. Для группировки предикатов и управления порядком вычислений можно использовать скобки.

Каждый из предикатов может содержать вложенные предикаты.Результат вычисления истинности утверждения получается в результате вычисления всех предикатов по направлению от внутренних к внешним.Каждый “уровень” вычисляется в порядке приоритета до тех пор, пока не будет получено значение истинности окончательного утверждения.