Windows Live ID Добро пожаловать на IT Community 
Регистрация

Стань частью ИТ-сообщества

Хочешь найти своих друзей, коллег или просто интересных людей со схожими интересами в ИТ-области? Не теряй время...

Присоединяйся к нам!

Александр Олейник

Евгений Журбенко

Павел Елисеев


Все участники

17 января 2009 г. - Posts

Просмотров: 1340
Ответов: 0

SELECT TOP и MAX()

отправлено 17 января 2009 г. 13:48 участником alexejs

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

Читать далее...
Читать далее

Блог

Календарь

«Январь 2009 г.»
ПнВтСрЧтПтСбВс
2930311234
567891011
12131415161718
19202122232425
2627282930311
2345678

Категории

Синдикация

Виртуальные сообщества

Сообщества сайтов (тэгами)