Использование инструкции SELECT в предложении WHERE

SELECT * FROM ScoresTable WHERE Score = 
  (SELECT MAX(Score) FROM ScoresTable AS st WHERE st.Date = ScoresTable.Date)

есть ли имя для описания с помощью оператора SELECT в предложении WHERE? Это хорошая / плохая практика?

будет ли это лучшей альтернативой?

SELECT ScoresTable.* 
FROM ScoresTable INNER JOIN 
  (SELECT Date, MAX(Score) AS MaxScore 
  FROM ScoresTable GROUP BY Date) SubQuery 
  ON ScoresTable.Date = SubQuery.Date 
  AND ScoresTable.Score = SubQuery.MaxScore

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

N. B. мне нужно больше, чем просто дата и оценка (например, имя)

7 ответов


Это называется коррелированным подзапросом. Он это использует.


Это совсем не плохая практика. Их обычно называют подзапрос, подзапроса или ВЛОЖЕННЫЙ ЗАПРОС.

Это относительно дорогая операция, но довольно часто встречаются много подзапросов при работе с базами данных, так как это единственный способ выполнить определенные операции с данными.


есть гораздо лучший способ достичь желаемого результата, используя SQL Server аналитические (или оконные) функции.

SELECT DISTINCT Date, MAX(Score) OVER(PARTITION BY Date) FROM ScoresTable

Если вам нужно больше, чем просто комбинации даты и максимального балла, вы можете использовать функции ранжирования, например:

SELECT  *
FROM    ScoresTable t
JOIN (   
    SELECT 
        ScoreId,
        ROW_NUMBER() OVER (PARTITION BY Date ORDER BY Score DESC) AS [Rank] 
        FROM ScoresTable
) window ON window.ScoreId = p.ScoreId AND window.[Rank] = 1

вы можете использовать ранг() вместо функции row_number() если вы хотите, чтобы несколько записей были возвращены, если они оба имеют одинаковый Макс (оценка).


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


Это коррелированный подзапрос.

(это" вложенный " запрос-это очень нетехнический термин, хотя)

внутренний запрос принимает значения из внешнего запроса (ст.Дата = ScoresTable.Дата), таким образом, она вычисляется один раз для каждой строки во внешнем запросе.

существует также некоррелированная форма, в которой внутренний запрос независим, поскольку как таковой выполняется только один раз.

например

 SELECT * FROM ScoresTable WHERE Score = 
   (SELECT MAX(Score) FROM Scores)

нет ничего неправильно использовать подзапросы, за исключением тех случаев, когда они не нужны :)

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

SELECT Max(score), Date FROM ScoresTable 
Group By Date

в вашем случае, почему бы не использовать предложение GROUP BY и HAVING вместо присоединения таблицы к себе. Вы также можете использовать другие полезные функции. ссылка


подзапрос-это имя.

иногда это требуется, но хорошо/плохо зависит от того, как он применяется.