다음을 통해 공유


SELECT TOP и MAX()

Один товарищ недавно парился с запросом вида select max(поле) from (select top N * from таблица) t. Давайте я возьму в качестве примера таблицу Northwind.dbo.Orders и на ней вкратце обрисую ситуацию. Предположим, товарищу надо найти максимальное значение поля OrderID, но не во всей таблице, а только среди ее первых 10 записей. Товарищ уже асилел конструкции TOP/BOTTOM, потому знает, что получить первые 10 OrderID можно так:

select top 10 OrderID from Northwind..Orders--------------------------------------------OrderID10248102491025010251102521025310254102551025610257

Скрипт 1

а максимум из них, соответственно, так:

select max(t.OrderID) from (select top 10 OrderID from Northwind..Orders) t
Скрипт 2

Выполняет, стало быть, запрос и получает значение 11077, которое, безусловно, является максимальным, но аж во всей таблице Orders.
Но товарищ вдобавок проходил common table expressions, потому он переписывает запрос так:
 

;with cte as (select top 10 OrderID from Northwind..Orders)select max(OrderID) from cte

Скрипт 3

И получает снова 11077. Потому что подзапрос, он и в Африке подзапрос, каким бы СТЕ его не окрестили. И если он не работает, то ни чучелом, ни тушкой, никак.
На всякий случай товарищ скидывает результаты во временную таблицу и делает select max() из нее. Получается, натурально, 10257, что окончательно убеждает его в выводе, что виноват подзапрос. Чтобы посмотреть, что же возвращается в результате подзапроса, товарищ переписывает Скрипт 2 как

select * from (select top 10 OrderID from Northwind..Orders) tСкрипт 4

и получает тот же набор записей, что и в рез-те Скрипта 1. То есть подзапрос-то работает нормально. Видимо, это глючит функция max(). Товарищ последовательно заменяет max() на другие агрегатные функции

select count(*) from (select top 10 OrderID from Northwind..Orders) t---------------------------------------10

Скрипт 5

select sum(x) from (select top 10 OrderID from Northwind..Orders) t(x)-----------------------102525

Скрипт 6

Трясущимися руками он складывает 10248, 10249, ..., 10257 на калькуляторе (железном, электрическом), потому что он уже не доверяет ни экселю, ни встроенному калькулятору, ничему, что находится под управлением операционной системы Windows. Сумма сходится. Он снова выполняет Скрипт 1 и снова получает максимум по всей таблице. Товарищ взвывает и бежит биться головой об стенку.

Помогите, пожалуйста, товарищу - https://sqlclub.ru/forum/viewtopic.php?f=4&t=1574. Какой момент он упустил сделать в запросе, что его так не на шутку колбасит. Время уже позднее, а он стучится об стенку все сильнее. Соседи-то ни в чем не виноваты.

Comments

  • Anonymous
    June 01, 2009
    PingBack from http://paidsurveyshub.info/story.php?id=75891

  • Anonymous
    June 04, 2010
    Ну я прям из жизни выдернул... select top 1 a.dt from (select top 11 dt as dt from scheldue where dt>='02/06/10 9:59' order by dt) a order by dt desc

  • Anonymous
    June 04, 2010
    Ну я прям из жизни выдернул... select top 1 a.dt from (select top 11 dt as dt from scheldue where dt>='02/06/10 9:59' order by dt) a order by dt desc

  • Anonymous
    March 05, 2013
    надо сортировку добавить, без нее данные случайно выбираются при селест топ 10