Урок 4: Подзапросы — Когда Одного Запроса Недостаточно!


Lesson 4

Урок 4: Подзапросы — Когда Одного Запроса Недостаточно!

Привет снова, отважный исследователь данных! Если ты дошел до этого момента, то, наверное, думаешь: “Да это ж все проще пареной репы!” Но как только ты решаешь, что стал настоящим повелителем своих таблиц, PostgreSQL достает из рукава новый козырь: Подзапросы. Вот тут-то и начинается настоящая игра! Подзапросы — это как маленькие секретные миссии, спрятанные внутри основного запроса, которые выполняют всю грязную работу за кулисами.

Что такое Подзапрос?

Представь себе, что ты в ресторане. Ты заказал себе пиццу (основной запрос), но тихонько добавляешь официанту: “А еще, если есть возможность, добавьте побольше сыра.” Вот это и есть твой подзапрос! Подзапрос — это запрос, вложенный внутри другого запроса, который используется для уточнения или расширения результата основного запроса.

Подзапросы полезны в тех случаях, когда одного запроса просто недостаточно, например:

  • Найти самых успешных рыцарей (по количеству выполненных заданий).
  • Узнать, какие драконы сожгли больше трех деревень.
  • Определить, какие рыцари нуждаются в, скажем, дополнительных тренировках.

Типы Подзапросов

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

  1. Подзапросы, возвращающие одну строку: Они возвращают только одну строку. Идеально для быстрых проверок.
  2. Многозапросные Подзапросы: Возвращают несколько строк. Отлично подходят для сравнения списков!
  3. Скалярные Подзапросы: Возвращают одно значение. Круто подходят для скрытых сравнений.
  4. Коррелированные Подзапросы: Это настоящие шпионы — они знают, что происходит в основном запросе, и адаптируются на лету.

Давай посмотрим, как это работает!

Использование Подзапросов с SELECT

Начнем с простого примера. Допустим, у тебя есть таблица rycari, и ты хочешь узнать, какой рыцарь выполнил больше всего заданий:

SELECT imya
FROM rycari
WHERE vypolnennye_missii = (SELECT MAX(vypolnennye_missii) FROM rycari);

Этот маленький подзапрос (SELECT MAX(vypolnennye_missii) FROM rycari) выполняет свою работу, возвращает максимальное значение и передает его основному запросу, который затем говорит: “Покажи мне только тех рыцарей, у кого столько же выполненных миссий.”

Подзапросы в FROM

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

SELECT korolevstvo, AVG(vypolnennye_missii)
FROM (SELECT imya, korolevstvo, vypolnennye_missii FROM rycari) AS sub_rycari
GROUP BY korolevstvo;

Здесь наш подзапрос работает как временная таблица, ограничивая данные перед тем, как основной запрос начнет их обрабатывать.

Подзапросы в WHERE

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

SELECT imya
FROM rycari
WHERE vypolnennye_missii > (SELECT AVG(vypolnennye_missii) FROM rycari);

Подзапрос вычисляет среднее значение, а основной запрос говорит: “Покажи мне только тех рыцарей, которые выше среднего!” (Те, кто не протирает доспехи зря, короче говоря.)

Коррелированные Подзапросы: Шпионы SQL

Коррелированные подзапросы — это самые хитрые из всех. Они выполняются для каждой строки основного запроса и могут ссылаться на его столбцы. Допустим, ты хочешь узнать, какие рыцари выполнили больше миссий, чем средний показатель по их собственному королевству:

SELECT imya, korolevstvo
FROM rycari AS r1
WHERE vypolnennye_missii > (SELECT AVG(vypolnennye_missii) 
                            FROM rycari AS r2 
                            WHERE r2.korolevstvo = r1.korolevstvo);

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

Подзапросы в SELECT

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

SELECT imya, 
       vypolnennye_missii, 
       (SELECT AVG(vypolnennye_missii) FROM rycari) AS obshchaya_srednyaya
FROM rycari;

Теперь у тебя есть четкое сравнение, и все благодаря этому маленькому подзапросу, что прячется в основном запросе.

Объединим Все: Великий Парад Подзапросов!

Вот сценарий, который покажет все, что мы узнали:

Ты хочешь найти рыцарей, которые выполнили больше заданий, чем средний показатель, но только если они из королевств, где среднее количество миссий выше 3. Звучит сложно? Вот магия:

SELECT imya
FROM rycari
WHERE vypolnennye_missii > (SELECT AVG(vypolnennye_missii) 
                            FROM rycari) 
AND korolevstvo IN (SELECT korolevstvo 
                    FROM rycari 
                    GROUP BY korolevstvo 
                    HAVING AVG(vypolnennye_missii) > 3);

Этот монстр-запрос использует подзапросы и в WHERE, и в IN условиях. Это как командовать целой армией маленьких запросов!

Что Мы Сегодня Узнали?

Сегодня мы погрузились в мир подзапросов:

  • Подзапросы, возвращающие одну строку: Возвращают одну строку, используются для точных сравнений.
  • Многозапросные Подзапросы: Возвращают несколько строк, идеально для списков.
  • Скалярные Подзапросы: Возвращают одно значение, для скрытых сравнений.
  • Коррелированные Подзапросы: Динамически подстраиваются под основной запрос.

Что Дальше?

В следующем уроке мы разберем CTE и Оконные Функции. Готовься поднять свои навыки SQL на новый уровень!


Добро пожаловать в мир подзапросов. Пусть ваши вложенные запросы всегда будут четкими, а результаты — точными!