MySQL выборка больше одной записи во вложенном подзапросе

Есть в SQL, а в том числе и в MySQL такая замечательная вещь как вложенные запросы (знаком с ней давно), бывают разные случаи, когда использование таких запросов может пригодиться.

1
SELECT * FROM table1 WHERE field > (SELECT max(id) FROM table2)

Совершенно абстрактный пример, чтобы показать смысл.

В данном случае, когда результат вложенного запроса используется в линейном условии в основном,  он (результат) должен быть только одним полем, потому что иначе запрос просто не имеет смысла

Также, в WHERE можно прописывать такую замечательную вещь как IN (NOT IN) (об этом я также знал уже довольно давно)

1
SELECT * FROM table WHERE field in ('value1', 'value2')

И вот тут самое интересное:

Долгое время, используя вложенные подзапросы только как в примере 1, я думал, что вложенные подзапросы всегда должны возвращать только одно поле, но оказывается, результат вложенного подзапроса можно скармливать в IN, и тогда результатом вложенного запроса может быть не одна строка.

Например, следующий нехитрый подзапрос выберет из таблицы с многоуровневым бесконечным каталогом все конечные элементы не имеющие потомков

1
SELECT t1.* FROM table as t1 WHERE id NOT IN (SELECT top FROM table as t2)

Ну не прекрасно ли это?

Другими словами, мы выбираем все записи, id которых никому не являются top’ами в этой же таблице.

Единственный пугающий и узкий момент в подобном запросе — это время выполнения. Но к счастью в MySQL есть кэширование результатов запроса, и для каких-то выгрузок данных, действий в панелях управления подобный запрос неплохо подойдет (на небольших таблицах более усложненные подобные запросы отрабатывали в районе 1 секунды на шаред-хостинге). Конечно пихать такое на посещаемый сайт для вывода каких-то рюшечек при выводе элементов каталога не стоит, но как уже сказано выше, где-нибудь в редко-используемом месте это неплохо подходит, ну и к тому же есть смысл кешировать такое уже средствами языка программирования и тогда проблем тоже нет.

Тут важна идея.

Подобное можно реализовать несколькими запросами и несклолькими циклами в программном коде, а можно все это сформировать в виде одного запроса и отдать это на аутсорсинг серверу MySQL 🙂 Второе лучше и интересней

 

Комментарии:


  1. Павел

    Вообще вложенные подзапросы с использование конструкции in очень тормознутые!

    Например:
    SELECT * FROM t1 WHERE id NOT IN (SELECT id FROM t2);

    Или тоже самое, но с использованием джоина:
    SELECT t1.*
    FROM t1 LEFT JOIN t2 ON t1.id = t2.id
    WHERE t2.id IS NULL;

    С джоином подобный запрос работать будет в разы быстрее…




YouTube бесплатно навести проклятие порчу