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
--------------------------------------------
OrderID
10248
10249
10250
10251
10252
10253
10254
10255
10256
10257
Скрипт 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 и снова получает максимум по всей таблице. Товарищ взвывает и бежит биться головой об стенку.


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


Comments (4)

  1. Shampur says:

    Ну я прям из жизни выдернул…

    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

  2. Shampur says:

    Ну я прям из жизни выдернул…

    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

  3. sv says:

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

Skip to main content