Практики · занятие 6

Средство управления базами данных 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. Разминка

Разминка 1

Заполните схему: для каждого типа геометрии (точка, линия, полигон) выпишите функции свойств.

показать ответ

Точка — ST_X, ST_Y; линия — ST_Length, ST_StartPoint, ST_EndPoint, ST_NPoints; полигон — ST_Area, ST_NRings, ST_ExteriorRing.

Разминка 2

Проиллюстрируйте операции: 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» одним из трёх способов:

  1. меню База данных → Окно SQL;
  2. кнопкой на панели менеджера (ЛКМ);
  3. клавишей F2.
Окно SQL менеджера БД
Повторение

Найдите все блоки в Манхэттене, где проживает более 1000 человек.

показать решение
SELECT * FROM nyc_census_blocks
WHERE boroname = 'Manhattan' AND popn_total > 1000;

Результат запроса можно загрузить как новый слой прямо из окна SQL: поставьте галочку «Загрузить как новый слой» и выберите столбец с геометрическим типом данных.

Загрузка результата запроса как слоя
Отображение векторных слоёв из запроса

3. Прикладная задача: население округов

Задача: создать карту населения по округам Нью-Йорка. Посмотрим на данные внимательно:

Соединить их позволяет оператор 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;

Каждый район получает суммарное население своего округа: все районы одного округа окрашиваются одинаково, и слой районов превращается в карту населения округов.

Типичная ошибка Сгруппировать этот JOIN по boroname и просуммировать popn_total: соединение «каждый с каждым» внутри округа дублирует блоки для каждого района, и сумма округа завышается кратно числу его районов. Группируйте по району (n.name) — тогда каждый блок в группе учтён один раз; а если нужна статистика по каждому району в отдельности, соединяйте не по boroname, а пространственным предикатом ST_Intersects(n.geom, c.geom).

3.1. Песочница: JOIN и GROUP BY

Фрагмент данных: пять округов, по несколько блоков на округ. Сравните пресеты: «население по округам» даёт честные суммы прямо по блокам; «JOIN без GROUP BY» показывает взрыв строк; «JOIN + GROUP BY по району» — рабочий вариант из раздела 3 (каждый район получает население своего округа); а «ловушка: GROUP BY boroname» — ошибку из врезки: суммы Бруклина и Манхэттена завышены ровно во столько раз, сколько районов округа попало во фрагмент. Сравните числа с первым пресетом.

SQL-песочница · JOIN двух таблиц
Схема: nyc_census_blocks(blkid, boroname, popn_total) · nyc_neighborhoods(name, boroname) — иллюстративный фрагмент

4. Символизация по диапазонам значений

  1. После выполнения запроса загрузите слой (галочка и столбец геометрии, раздел 2).
  2. ПКМ по слою → Свойства → вкладка «Стиль».
  3. Измените стиль отображения с «Простой символики» на «Символизация по диапазонам значений».
Выбор символизации по диапазонам значений

Устройство окна: выбирается столбец количественной характеристики, настраивается цветовая шкала, алгоритм поиска интервалов и количество интервалов:

Окно настройки символизации

Параметры для карты населения: значение — total_population, линейка цвета — Greens, режим — логарифмическая шкала, классов — 5; далее «Классифицировать» и «Применить».

Карта суммарного населения округов
Почему логарифмическая шкала? Население округов различается в разы — на линейной шкале почти все округа сливаются в один класс (вспомните «тяжёлые хвосты» из практики 9). Логарифмические ступени распределяют объекты по классам равномернее.

4.1. Карта плотности населения

  1. ПКМ по слою → Дублировать слой.
  2. В копии замените параметры отображения: значение → выражение плотности. Нажмите ε (кнопку выражения) и введите "total_population" / ($area / 1000000) — население на км²; функция $area в QGIS возвращает площадь полигона.
  3. Удалите старые значения интервалов («Удалить все») и классифицируйте заново.
  4. Визуально сравните результаты: карта абсолютного населения и карта плотности расставляют акценты по-разному.
Карта общего населения
Карта плотности населения

Шкалу можно собрать и вручную: кнопка «+» добавляет ступень, подписи легенды вбиваются самостоятельно, в конце — «Применить» (этот приём пригодится в практике 7 и практике 9).

5. Импорт собственных данных в базу

Загрузка внешних файлов в проект: файл можно просто перебросить в окно «Слои». Проверьте таблицу атрибутов: если атрибуты на русском языке читаются — кодировка выбрана верно, иначе смените её на Windows-1251 (зависит от компьютера, на котором готовился файл).

Проверка кодировки атрибутов

Импорт слоя в базу через менеджер БД (кнопка «Импорт слоя/файла»):

  1. Присоединитесь к своей БД: выберите её из списка, раскройте, выберите схему public.
  2. Для векторного слоя включите пункты: первичный ключ, поле геометрии, создать пространственный индекс.
  3. Для табличного слоя (без геометрии) достаточно первичного ключа.
Импорт векторного слоя в базу

Вкладка «Связи» в свойствах слоя присоединяет атрибутивные данные одного слоя к другому по ключевым атрибутам (внешнему и главному ключу) — работает аналогично оператору JOIN, только через графический интерфейс: укажите, по каким полям происходит объединение, и сравните таблицу атрибутов до и после.

Вкладка Связи
Таблица атрибутов после присоединения

6. Дополнительные задания

Задание 1

Вычислите площадь Гарлема (Harlem) в разных проекциях: 2263, 32618 и 26918 (ST_Area — расчёт площади, ST_Transform — преобразование проекции).

подсказка

Решение разобрано в практике 5; не забудьте про разницу единиц (футы в 2263 против метров в UTM-зонах).

Задание 2

Выведите все остановки метро внутри Чайнатауна.

показать решение
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).

Контрольные вопросы

Источники

  1. 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).
  2. PostgreSQL 15 Documentation. Joins Between Tables : [сайт]. — URL: https://www.postgresql.org/docs/15/tutorial-join.html (дата обращения: 18.08.2026).
  3. PostGIS Workshop. Spatial Joins : [сайт]. — URL: https://postgis.net/workshops/postgis-intro/joins.html (дата обращения: 18.08.2026).