Подзапросы

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

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

[Примечание]Примечание

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

Возможны три основные варианты использования подзапросов:

  1. Результатом выполнения подзапроса является единственное значение. Это возможно, например, если в подзапросе вычисляется значение агрегирующей функции по всем записям выборки. Такие подзапросы могут использоваться в составе выражений в командах выборки, наряду с обычными значениями и функциями.

    Использование подзапроса возвращающего единственное значение

    SELECT b.sys, b.Geometry.STArea(), k.sys   
    FROM Здания AS b, Кварталы AS k 
    WHERE b.Geometry.Within(k.Geometry) 
    AND b.Geometry.STArea()/  
    (SELECT SUM(b2.Geometry.STArea()) 
    FROM Здания AS b2 
    WHERE b2.Geometry.STWithin(k.Geometry)) > 0.1 

    где:

    • конструкция b.Geometry.STArea() возвращает площадь объекта слоя с псевдонимом b;

    • для слоя Здания задается псевдоним b. По этому псевдониму можно обращаться к полям записи запрашиваемой в основной команде выборки;

    • конструкция b.Geometry.Within(k.Geometry) проверяет, располагается ли здание внутри квартала;

    • результатом выполнения вложенного запроса является суммарная площадь зданий в квартале в который входит искомое здание;

    • в подзапросе происходит обращение к объекту слоя Кварталы из основной выборки.

    Приведенный запрос находит объекты слоя Здания (или просто здания) располагающиеся внутри объектов слоя Кварталы (кварталов), находится общая площадь зданий в данном квартале и выводятся информация о записях площадь которых больше 10% от общей площади зданий в данном квартале.

    Вывод результата подзапроса

    SELECT b.sys, b.Geometry.STArea()/(
    SELECT SUM(b2.Geometry.STArea()) FROM Здания AS b2 
    WHERE b2.Geometry.STIntersects(k.Geometry)), k.sys
    FROM Здания AS b, Кварталы AS k 
    WHERE b.Geometry.intersects(k.Geometry)
    AND b.Geometry.STArea()/(
    SELECT SUM(b2.Geometry.STArea()) FROM Здания AS b2 
    WHERE b2.Geometry.STIntersects(k.Geometry)) > 0.1

    Приведенный запрос аналогичен рассмотренному в предыдущем примере, за тем исключением, в результате выполнения команды выборки выводятся не площади объектов, а их отношение к общей площади объектов в квартале.

  2. Результатом выполнения запроса является список значений. Такие подзапросы используются в качестве операнда оператора проверки значений по списку IN («Задание условий отбора полей»). Подзапросы такого вида должны возвращать список из значений одного поля, либо выражения (после ключевого слова SELECT указывается только одно выражение для вывода).

    Использование подзапроса возвращающего список значений

    SELECT sys, Улица  
    FROM Здания WHERE Улица IN (
    SELECT Улица from Здания GROUP BY Улица HAVING COUNT(*)>20
    )

    Запрос возвращает список записей в которых значение поля Улица входит в список улиц имеющих более двадцати записей.

  3. Результатом выполнения подзапроса является любое значение. Такие подзапросы используются в качестве операнда оператора EXISTS проверяющего, вернет ли подзапрос какое-либо значение («Задание условий отбора полей»). На подзапросы такого вида не накладывается никаких ограничений.

    Использование подзапроса с оператором EXISTS

    SELECT sys FROM Кварталы AS k WHERE EXISTS( 
    SELECT * FROM Здания AS b where b.Geometry.Intersects(k.Geometry) AND 
    b.perimeter < k.perimeter /13
    )

    Запрос возвращает список объектов слоя Кварталы для которых существуют объекты слоя Здания которые взаимодействуют с данными кварталами и при этом периметр таких зданий не менее чем в 13 раз меньше периметра данных кварталов.