Найти тему
Властелин машин

Магия подзапросов в SQL

Оглавление

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

Наши демонстрационные примеры будут базироваться на статистике всех поединков, организованных UFC за годы своего существования (скачаны скрапером с сайта ufcstats.com , описание можно найти здесь):

В частности работать будем с составленным ранее на основании этой статистики представлением (f_y), содержащим имена бойцов и годы их выступлений:

-2

Некоррелированные подзапросы

Это фактически обычные запросы, включенные во внешний в качестве подвыражений. Например, выведем из 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

-3

Можно вернуть аналогичные результаты альтернативным способом (наш подзапрос теперь расположился не в 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
-4

Помните, что подзапросы заключаются в круглые скобки. В случае использования некоррелированных подзапросов можно перед включением в финальное выражения проверить их результаты как для обычного запроса:

SELECT fighter
FROM f_y AS f_y_i
WHERE f_y_i.year < 2019
-5

Коррелированные подзапросы

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

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):

-6

-7