Раздел 42 · Аналитика данных с нуля

Подзапросы и EXISTS

junior~15 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

Мира · маркетолог магазина настолок «Кубик»

Хочу значок «премиум» в каталоге. Только честно: варгейм за пять тысяч это норма, а карточная игра за тысячу уже роскошь. И пришли список всех, кто хоть раз что-то возвращал, хочу спросить у них, что пошло не так.

Чтобы отметить «премиум», нужно сначала узнать среднюю цену, а потом сравнить с ней каждую игру. Два шага, и второй зависит от первого. Можно выполнить первый запрос, переписать число на бумажку и вставить во второй. А можно поручить это базе: вложить один запрос в другой.

Запрос в скобках

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

Средняя цена игры в каталоге:

SELECT round(avg(price), 2) FROM products;
 round
---------
 2283.44

Теперь вместо числа подставим сам запрос:

SELECT title, genre, price
FROM products
WHERE price > (SELECT avg(price) FROM products);

Подзапрос вернул одно значение, одну строку и один столбец. Такой подзапрос называют скалярным, и его можно ставить везде, где ждут обычное число или строку. Дороже средней по каталогу 51 игра. Но Мира просила честно: сравнивать варгейм за 4671 ₽ в среднем с карточной игрой за 636 ₽ бессмысленно.

Сравнение внутри жанра

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

SELECT p.title, p.genre, p.price
FROM products p
WHERE p.price > (
  SELECT avg(q.price)
  FROM products q
  WHERE q.genre = p.genre
);

Внутри подзапроса стоит q.genre = p.genre, где p это строка снаружи. Такой подзапрос называют коррелированным: он пересчитывается для каждой игры, как вопрос, который продавец задаёт себе у каждой полки: «а сколько в среднем стоит этот жанр?».

Премиумом стали 53 игры. Среди карточных, например, «Крепость Степи» за 1140 ₽: по меркам каталога дёшево, по меркам карточных игр почти вдвое дороже средней.

урок из курса

Урок из курса «Аналитика данных с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.

Оплата пока не подключена: премиум и курсы открываются промокодом.