Использование инструкции SELECT в предложении WHERE - PullRequest
9 голосов
/ 21 июня 2011
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

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

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

Ответы [ 7 ]

7 голосов
/ 21 июня 2011

Это совсем не плохая практика. Их обычно называют SUBQUERY , SUBSELECT или NESTED QUERY .

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

6 голосов
/ 21 июня 2011

Это называется коррелированным подзапросом. У него есть свои цели.

3 голосов
/ 21 июня 2011

Существует гораздо лучший способ достичь желаемого результата, используя аналитические (или оконные) функции 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

Возможно, вы захотите использовать RANK () вместо ROW_NUMBER () , если вы хотите, чтобы несколько записей были возвращены, если они обе используют один и тот же MAX (счет).

2 голосов
/ 21 июня 2011

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

1 голос
/ 02 марта 2016

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

1 голос
/ 21 июня 2011

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

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

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

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

например,

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

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

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

SELECT Max(score), Date FROM ScoresTable 
Group By Date
0 голосов
/ 21 июня 2011

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

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

...