SELECT с ограничением количества возвращаемых значений

AlxR
Дата: 04.01.2001 13:17:38
Привет всем!
Такой вот вопрос:
SELECT возвращает большое количество значений.
Требуется разбить эти значения на страницы (приложение для интернета). В MySQL в SELECTе можно применить LIMIT(), где в скобках задать требуемый диапазон значений. А как поступить в MS SQL2000?
Главная цель - максимально сократить время выполнения запроса.
Мои варианты такие:
1. Пользоваться TOP. Минус - при необходимости отображения одной из последних страниц время выполнения запроса будет приближаться к варианту как без TOP + время на отброс значений, не попавших в диапазон на уровне приложения.
2. Сделать с использованием курсоров. Но тут куча сложностей, не хотелось бы.

Кто что посоветует? Заранее спасибо
wlad
Дата: 05.01.2001 10:55:24
Могу сказать одно - не пользуйтесь курсорами, это очень долго
SergSuper
Дата: 05.01.2001 11:44:09
Чего-то ничего красивого в голову не приходит.

Можно сделать дополнительное поле, а перед тем как надо выводить апдейтить его:

@i=0
update tbl set @i=@i+1, ord=@i

Ну а дальше выводить по диапазонам

если задан какой-то ключ, по которому должны выводиться записи можно делать примерно так:

select top 100 * from tbl where key>@k order by key
select top 100 @k=key from tbl where key>@k order by key

Здесь получается чтение два раза, но в любом случае это будет быстрее чем с курсорами.
axel
Дата: 05.01.2001 15:18:46
1. в исходной таблице (Т1) необходимо определить ключевые поля.
2. создать вспомогательную таблицу (Т2), в которой будут присутствовать все ключевые поля из Т1 + столбец (Ord), содержащий порядковый номер записи в Т2.
3. использовать простой запрос
SELECT T1.*
FROM T1,T2
WHERE T2.Ord BETWEEN (@CurrentPageNumber-1)*@RowsPerPage+1 AND @CurrentPageNumber*@RowsPerPage
AND T1.ключевые_поля = T2.ключевые_поля_из_T1
ORDER BY ...
zinin
Дата: 05.04.2001 20:16:39
как проще обычным запросом обновить столбец (Ord), содержащий порядковый номер записи в Т2.
Alexander_Rudenko
Дата: 05.04.2001 20:52:43
2 axel
Это все хорошо, но как быть, если на таблицу наложен фильтр?
Genady
Дата: 06.04.2001 11:16:03
Не знаю как будет по скорости, но можно попробовать так:

select * into #temp_tbl from your_tbl where 1=2
alter table #temp_tbl add NewID int identity (1,1)

insert into #temp_tbl select * from your_tbl where [условия]

select * from #temp_tbl where NewID between [начало диапазона] and [конец диапазона]
Glory
Дата: 06.04.2001 12:07:12
IMHO можно немного упростить
select identity (int, 1,1) AS NewID, your_tbl.* into #temp_tbl from your_tbl where [условия]

На серевере 2хPIII-733, RAM 1Gb, HDD 36Gb на таблице с 250 000 записей работает до 5 секунд максимум, на таблице с 10 000 000 записей - больше 10 минут (правда выборки были без where и join)
Genady
Дата: 06.04.2001 13:18:36
>IMHO можно немного упростить
Ну в общем то можно, я когда писал свой вариант на всякий случай учел вот это http://www.sql.ru/subscribe/037.shtml#2
Kostya79
Дата: 06.04.2001 13:53:19
Тебе надо вернуть ВСЕ значения клиенту, а уже на клиенте разобраться, что выводить (тот же листинг и т.д. и т.п.).

К примеру, если нужно первые 20 записей, то делаешь на клиенте:
i=1

while i<20 do
print rec
MoveTonextrec
i++
loop

P.S. Чудовищный язык программирования я тут изобрел.