ВЫБРАТЬ с несколькими подзапросами к одной и той же таблице

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

SELECT TStudents.*,
       BookName = (SELECT TOP 1 BookName 
                     FROM TBookCheckouts 
                    WHERE StudentID = TStudents.ID 
                 ORDER BY DateCheckedOut DESC),
       BookAuthor = (SELECT TOP 1 BookAuthor 
                       FROM TBookCheckouts 
                      WHERE StudentID = TStudents.ID 
                   ORDER BY DateCheckedOut DESC),
       BookCheckout = (SELECT TOP 1 DateCheckedOut 
                         FROM TBookCheckouts 
                         WHERE StudentID = TStudents.ID 
                     ORDER BY DateCheckedOut DESC)
   FROM TStudents

(Для этого примера, пожалуйста, игнорируйте тот факт, что TBookCheckouts, вероятно, следует разделить в TCheckouts и TBooks)

То, что я пытаюсь проиллюстрировать: у меня есть много подзапросов для столбцов из одной и той же таблицы. Я также склонен отсортировать эти подчиненные таблицы по дате, чтобы получить самую последнюю запись, поэтому это не так просто (по крайней мере, для меня), как выполнение LEFT JOIN. Однако обратите внимание, что, за исключением того, какое поле возвращается, я, по сути, выполняю один и тот же подзапрос 3 раза. SQL Server может быть достаточно умен, чтобы оптимизировать это, но я думаю, что нет (мне определенно нужно научиться лучше читать планы выполнения ...).

Хотя такое структурирование может иметь преимущества (иногда это заканчивается будучи более читабельным, если у меня есть тонны подзапросов и подтаблиц), это не кажется особенно эффективным.

Я рассмотрел возможность выполнения LEFT JOIN из производной таблицы, возможно, включая ROW_NUMBER () и PARTITION BY, но я просто не могу собрать все воедино.

13
задан OMG Ponies 11 October 2010 в 15:59
поделиться