Средство управления базами данных QGIS. Оператор JOIN
- О чём это занятие
- QGIS превращается из «просмотрщика» в полноценный клиент базы данных: окно SQL менеджера БД, загрузка результатов запросов как слоёв — и главная звезда занятия, оператор JOIN, которым мы собираем карту населения округов Нью-Йорка из двух таблиц.
- Аннотация
- Занятие начинается с разминки по пространственным отношениям и типам геометрий из практики 5. Затем изучается окно SQL плагина DB Manager — три способа его вызова и загрузка результата запроса как слоя с указанием столбца геометрии. Прикладная задача формулируется честно: в таблице районов нет населения, в таблице блоков — названий районов на нужном уровне обобщения; решение — JOIN по общему полю boroname с группировкой и суммированием. Разобран синтаксис JOIN … ON, показано, почему без GROUP BY результат непригоден, и собран итоговый запрос суммарного населения округов. Песочница позволяет прогнать все варианты на фрагменте данных. Дальше — картография: символизация по диапазонам значений с логарифмической шкалой, дублирование слоя для карты плотности, ручная настройка ступеней шкалы и легенды, вычисление плотности через функцию $area. Завершают занятие импорт собственных таблиц в базу через менеджер (первичный ключ, геометрия, пространственный индекс), вкладка «Связи» как графический аналог JOIN и дополнительные задания.
- Пререквизиты
- Практика 5 — пространственные отношения; JOIN в теории — экспресс-занятие 3 и лекция 2.
- Материалы к занятию
- Учебная база nyc_data (включая таблицу nyc_census_sociodata) и QGIS с плагином DB Manager.
1. Разминка
Заполните схему: для каждого типа геометрии (точка, линия, полигон) выпишите функции свойств.
показать ответ
Точка — ST_X, ST_Y; линия — ST_Length, ST_StartPoint, ST_EndPoint, ST_NPoints; полигон — ST_Area, ST_NRings, ST_ExteriorRing.
Проиллюстрируйте операции: ST_Overlaps(A, B), ST_DWithin(A, B, R), ST_Contains(A, B), ST_Disjoint(A, B) — нарисуйте пары фигур, для которых каждая операция истинна.
показать ответ
ST_Overlaps — фигуры частично перекрываются (есть общая область, но ни одна не внутри другой); ST_DWithin — фигуры не дальше R друг от друга (в том числе касаются или пересекаются); ST_Contains — B целиком внутри A; ST_Disjoint — фигуры не имеют общих точек. Проверить себя можно в тренажёре практики 5.
2. Окно SQL менеджера БД
Плагин DB Manager знаком по прошлым занятиям; сегодня — его главный инструмент. Найдите свою БД в списке и раскройте её, затем вызовите «Окно SQL» одним из трёх способов:
- меню База данных → Окно SQL;
- кнопкой на панели менеджера (ЛКМ);
- клавишей F2.
Найдите все блоки в Манхэттене, где проживает более 1000 человек.
показать решение
SELECT * FROM nyc_census_blocks WHERE boroname = 'Manhattan' AND popn_total > 1000;
Результат запроса можно загрузить как новый слой прямо из окна SQL: поставьте галочку «Загрузить как новый слой» и выберите столбец с геометрическим типом данных.
3. Прикладная задача: население округов
Задача: создать карту населения по округам Нью-Йорка. Посмотрим на данные внимательно:
- в таблице
nyc_census_blocksданные по населению есть (popn_total по каждому из 38 794 блоков) — но блоки слишком мелкие для карты округов; - в таблице
nyc_neighborhoodsесть геометрия районов — но данных по населению нет.
Соединить их позволяет оператор JOIN — операция, которая объединяет строки из нескольких таблиц:
SELECT столбцы FROM таблица1 JOIN таблица2 ON таблица1.столбец = таблица2.столбец WHERE условие GROUP BY столбец;
Попробуем соединить nyc_census_blocks и nyc_neighborhoods по общему полю boroname — но пока не пытайтесь отобразить результат: на каждый район приходятся тысячи блоков его округа, строк получается огромное количество. Необходимо сгруппировать и вычислить суммарное население округа для каждого района:
SELECT n.name, n.boroname, sum(c.popn_total) AS total_population, n.geom FROM nyc_neighborhoods n JOIN nyc_census_blocks c ON n.boroname = c.boroname GROUP BY n.name, n.boroname, n.geom;
Каждый район получает суммарное население своего округа: все районы одного округа окрашиваются одинаково, и слой районов превращается в карту населения округов.
3.1. Песочница: JOIN и GROUP BY
Фрагмент данных: пять округов, по несколько блоков на округ. Сравните пресеты: «население по округам» даёт честные суммы прямо по блокам; «JOIN без GROUP BY» показывает взрыв строк; «JOIN + GROUP BY по району» — рабочий вариант из раздела 3 (каждый район получает население своего округа); а «ловушка: GROUP BY boroname» — ошибку из врезки: суммы Бруклина и Манхэттена завышены ровно во столько раз, сколько районов округа попало во фрагмент. Сравните числа с первым пресетом.
nyc_census_blocks(blkid, boroname, popn_total) ·
nyc_neighborhoods(name, boroname) — иллюстративный фрагмент
4. Символизация по диапазонам значений
- После выполнения запроса загрузите слой (галочка и столбец геометрии, раздел 2).
- ПКМ по слою → Свойства → вкладка «Стиль».
- Измените стиль отображения с «Простой символики» на «Символизация по диапазонам значений».
Устройство окна: выбирается столбец количественной характеристики, настраивается цветовая шкала, алгоритм поиска интервалов и количество интервалов:
Параметры для карты населения: значение — total_population, линейка цвета — Greens, режим — логарифмическая шкала, классов — 5; далее «Классифицировать» и «Применить».
4.1. Карта плотности населения
- ПКМ по слою → Дублировать слой.
- В копии замените параметры отображения: значение → выражение плотности.
Нажмите ε (кнопку выражения) и введите
"total_population" / ($area / 1000000)— население на км²; функция$areaв QGIS возвращает площадь полигона. - Удалите старые значения интервалов («Удалить все») и классифицируйте заново.
- Визуально сравните результаты: карта абсолютного населения и карта плотности расставляют акценты по-разному.
Шкалу можно собрать и вручную: кнопка «+» добавляет ступень, подписи легенды вбиваются самостоятельно, в конце — «Применить» (этот приём пригодится в практике 7 и практике 9).
5. Импорт собственных данных в базу
Загрузка внешних файлов в проект: файл можно просто перебросить в окно «Слои». Проверьте таблицу атрибутов: если атрибуты на русском языке читаются — кодировка выбрана верно, иначе смените её на Windows-1251 (зависит от компьютера, на котором готовился файл).
Импорт слоя в базу через менеджер БД (кнопка «Импорт слоя/файла»):
- Присоединитесь к своей БД: выберите её из списка, раскройте, выберите схему public.
- Для векторного слоя включите пункты: первичный ключ, поле геометрии, создать пространственный индекс.
- Для табличного слоя (без геометрии) достаточно первичного ключа.
Вкладка «Связи» в свойствах слоя присоединяет атрибутивные данные одного слоя к другому по ключевым атрибутам (внешнему и главному ключу) — работает аналогично оператору JOIN, только через графический интерфейс: укажите, по каким полям происходит объединение, и сравните таблицу атрибутов до и после.
6. Дополнительные задания
Вычислите площадь Гарлема (Harlem) в разных проекциях: 2263, 32618 и 26918 (ST_Area — расчёт площади, ST_Transform — преобразование проекции).
подсказка
Решение разобрано в практике 5; не забудьте про разницу единиц (футы в 2263 против метров в UTM-зонах).
Выведите все остановки метро внутри Чайнатауна.
показать решение
SELECT s.name, s.geom FROM nyc_subway_stations s, nyc_neighborhoods n WHERE n.name = 'Chinatown' AND ST_Within(s.geom, n.geom);
ST_Within(точка, полигон) — станция целиком внутри границы района; подойдёт и ST_Contains(n.geom, s.geom).
Контрольные вопросы
-
Меню База данных → Окно SQL; кнопка на панели менеджера; клавиша F2. Помимо выполнения запросов, окно умеет загружать результат как новый слой QGIS — с указанием столбца геометрии.
-
Население лежит в nyc_census_blocks (по блокам), а геометрия районов — в nyc_neighborhoods, где населения нет. JOIN по общему полю boroname соединяет строки двух таблиц, а GROUP BY с sum(popn_total) сворачивает блоки в суммарное население по округам.
-
Каждый район округа соединится с каждым блоком того же округа — результат разбухнет до сотен тысяч строк. Правильный вариант: группировка по району (GROUP BY n.name, n.boroname, n.geom) — каждый район получит суммарное население своего округа; для статистики по каждому району в отдельности — пространственное соединение через ST_Intersects.
-
Когда значения различаются на порядки (население округов, «тяжёлые хвосты»): линейные ступени сваливают почти все объекты в один класс. Логарифмические ступени делят диапазон по множителям и распределяют объекты равномернее.
-
Дублировать слой и в символизации задать выражение через кнопку ε: "total_population" / ($area / 1000000) — население на квадратный километр; $area — системная функция площади текущего объекта. Затем удалить старые интервалы и классифицировать заново.
-
Первичный ключ (уникальная идентификация строк), поле геометрии (иначе таблица станет атрибутивной) и создание пространственного индекса (GiST — без него пространственные запросы сканируют всю таблицу). Для таблиц без геометрии достаточно первичного ключа.
-
По сути ничем — то же соединение по ключевым полям, но через графический интерфейс и без создания новой таблицы: присоединённые поля видны в атрибутах слоя, пока настроена связь. Для сложных запросов (агрегаты, условия) нужен полноценный SQL JOIN.
Источники
- QGIS Documentation. DB Manager Plugin : [сайт]. — URL: https://docs.qgis.org/3.34/ru/docs/user_manual/plugins/core_plugins/plugins_db_manager.html (дата обращения: 18.08.2026).
- PostgreSQL 15 Documentation. Joins Between Tables : [сайт]. — URL: https://www.postgresql.org/docs/15/tutorial-join.html (дата обращения: 18.08.2026).
- PostGIS Workshop. Spatial Joins : [сайт]. — URL: https://postgis.net/workshops/postgis-intro/joins.html (дата обращения: 18.08.2026).