В этой статье я расскажу о типах подзапросов в SQL, которые придают гибкость вашему запросу и позволяют реализовать в нем сложный функционал.
Наши демонстрационные примеры будут базироваться на статистике всех поединков, организованных UFC за годы своего существования (скачаны скрапером с сайта ufcstats.com , описание можно найти здесь):
В частности работать будем с составленным ранее на основании этой статистики представлением (f_y), содержащим имена бойцов и годы их выступлений:
Некоррелированные подзапросы
Это фактически обычные запросы, включенные во внешний в качестве подвыражений. Например, выведем из f_y количество бойцов, выступавших в 2019 г. и при этом ранее не принимавших участие в турнирах:
SELECT 2019 AS year, COUNT(fighter)
FROM (SELECT fighter
FROM f_y
WHERE year=2019
EXCEPT
SELECT fighter
FROM f_y
WHERE year<2019) AS f_y_dif
Можно вернуть аналогичные результаты альтернативным способом (наш подзапрос теперь расположился не в FROM, а в условии WHERE):
SELECT year, COUNT(fighter)
from f_y AS f_y_o
WHERE fighter NOT IN (SELECT fighter
FROM f_y AS f_y_i
WHERE f_y_i.year < 2019) AND year = 2019
GROUP BY year
Помните, что подзапросы заключаются в круглые скобки. В случае использования некоррелированных подзапросов можно перед включением в финальное выражения проверить их результаты как для обычного запроса:
SELECT fighter
FROM f_y AS f_y_i
WHERE f_y_i.year < 2019
Коррелированные подзапросы
В отличие от предыдущих данные подзапросы ссылаются на столбцы внешней таблицы. Рассмотрим на примере получения списка лет и количества бойцов, принимавших участие в поединках в текущем году в первый раз:
SELECT year, COUNT(fighter)
from f_y AS f_y_o
WHERE fighter NOT IN (SELECT fighter
FROM f_y AS f_y_i
WHERE f_y_i.year < f_y_o.year)
GROUP BY year
ORDER By year DESC
Как можно заметить, из внешней таблицы во внутреннем подзапросе фигурирует год выступления бойца (f_y_o.year):