Что такое table expressions в SQL?
Что проверяют
Владеете ли вы SQL за пределами того, что генерирует ORM. Ждут, что вы назовёте виды табличных выражений и понимаете главное: это именованный запрос, а не временная таблица с данными.
Как отвечать
Табличное выражение возвращает набор строк и используется там, где ожидается таблица. Видов четыре: производная таблица (подзапрос в FROM со своим псевдонимом), обобщённое табличное выражение через WITH, представление и встроенная табличная функция. Скалярный подзапрос в списке SELECT сюда не относится: он отдаёт одно значение, а не набор.
with recent as (
select user_id, max(created_at) as last_seen
from events
group by user_id
)
select u.id, r.last_seen
from users u join recent r on r.user_id = u.id;Требования общие: у каждого столбца должно быть имя, имена уникальны, сортировка внутри без ограничения строк смысла не имеет. Отличие обобщённого выражения в том, что на него можно сослаться несколько раз и объявить рекурсивным.
Про производительность: выражение по умолчанию не материализуется, оптимизатор встраивает его в общий план, и два обращения к одному выражению честно посчитают его дважды. В PostgreSQL материализацию можно затребовать явно. В работе на C# это видно с двух сторон: ORM сам строит производные таблицы для группировок и постраничного вывода, а обход иерархии проще написать рекурсивным выражением, чем выражать через методы запросов.
Где спотыкаются
Считают обобщённое выражение временной таблицей и выстраивают лестницу из пяти выражений подряд, ожидая, что каждая ступень посчитается один раз. Если промежуточный результат тяжёлый и нужен многократно, берут настоящую временную таблицу.
Пишут рекурсивное выражение без ограничителя глубины и получают бесконечный обход на данных с циклом в связях.
Заменяют соединение скалярным подзапросом в списке вывода, как в типовых примерах из справочника. Такой подзапрос считается для каждой строки внешнего запроса, и агрегат почти всегда лучше вынести в отдельное выражение и присоединить.