powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Вот такой вопрос !
29 сообщений из 29, показаны все 2 страниц
Вот такой вопрос !
    #32034669
Sanek
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть набор записей (неважно каких)
есть желание их получить , но в наборе записей - 1000 строк,а я хочу получить только с 100 по 200
т.е первые 100
select top 100
а остальные как ?
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034673
AnKa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Начнем с того, что обязательно должен быть первичный ключ (если такового нет - введи IDENTITY поле).
Допустим, Field1 - первичный ключ, тогда


Код: plaintext
1.
2.
3.
4.
5.
SELECT TOP  200  *
FROM Table1 T1 
LEFT JOIN
(SELECT TOP  100 
 FROM Tab1) as T2 ON T1.Field1=T2.Field1
WHERE T2.Field1 IS NULL


здесь выбираются 200 начиная с 101
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034677
AnKa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Блин, поправочка:

Код: plaintext
1.
2.
3.
4.
5.
SELECT TOP  200  T1.*
FROM Table1 T1 
LEFT JOIN
(SELECT TOP  100  *
 FROM Table1 ) as T2 ON T1.Field1=T2.Field1
WHERE T2.Field1 IS NULL
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034680
Rom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 АнКа - не работает такая штука ..
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034682
Rom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
SELECT TOP  100  *
FROM Objs T1 
LEFT JOIN
(SELECT TOP  200  *
 FROM Objs ) as T2 ON T1.OID=T2.OID
WHERE T2.OID IS NULL

может так ?
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034683
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
по-моему можно как-то так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
SELECT TOP  100  id, name
  from(
    SELECT TOP  100  id, name
      from (
        SELECT TOP  200  *
          FROM sysobjects order by  id)  as t
      order by id desc) as t2
order by id


можно вставлять во временню таблицу с identity. В любом случае получается горбато
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034687
Sanek
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо !
Классная идея !
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034693
Rom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
кстати переправленный вариант от АнКа работает на УРА
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034696
Фотография Александр Степанов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
create table #tab
(
	PK int identity( 1 , 1 ) not null,
	field varchar( 100 ) not null
)

insert into #tab(field) values('A')
insert into #tab(field) values('B')
insert into #tab(field) values('C')
insert into #tab(field) values('D')
insert into #tab(field) values('E')
insert into #tab(field) values('F')
insert into #tab(field) values('G')
insert into #tab(field) values('H')
insert into #tab(field) values('I')
insert into #tab(field) values('J')
insert into #tab(field) values('K')
insert into #tab(field) values('L')
insert into #tab(field) values('M')
insert into #tab(field) values('N')
insert into #tab(field) values('O')
insert into #tab(field) values('P')

 --select first 5 values
 
Select TOP  5  * from #tab order By PK

 --select second 5 values
 
Select TOP  5  
	t.* 
from 
	#tab t 
	inner join 
	(Select MAX(PK) PK from (Select TOP  5  * from #tab order By PK) t) tt 
		on t.PK>tt.PK order By t.PK

 --select third 5 values
 
Select TOP  5  
	t.* 
from 
	#tab t 
	inner join 
	(Select MAX(PK) PK from (Select TOP  10  * from #tab order By PK) t) tt 
		on t.PK>tt.PK order By t.PK


drop table #tab


Поле, по которому осуществляется сортировка, должно быть уникальным.
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034810
SM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А если усложнить задачу? Получить N ную порцию из M записей? Причем N и M - задаются пользователем? Эдакий пэйджинг ?
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034821
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я тут не досуге решил FAQ по этому вопросу написать, доделать полностью не успел, но вот что есть. Выношу на обсуждение, благо есть повод.

Glory, ау! У Вас была сделано такая штука, но я теперь хоть убей не могу ее найти.
===========================================
Создана тестовая таблица на 10000 записей.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
CREATE TABLE [dbo].[NTable] (
	[RowID] [int] IDENTITY ( 1 ,  1 ) NOT NULL ,
	[DDate] [datetime] NULL ,
	[NDate] [float] NULL 
)
GO

ALTER TABLE [dbo].[NTable] WITH NOCHECK ADD 
	CONSTRAINT [PK_rowcount] PRIMARY KEY  CLUSTERED 
	(
		[RowID]
	)  ON [PRIMARY] 
GO

 CREATE  INDEX [IX_NTable] ON [dbo].[NTable]([NDate]) ON [PRIMARY]
GO

С полями RowID и DDаte все ясно, про поле NDate - несколько попозже.

Задача. Выделить m записей начиная с позиции n.
Записи должны быть отсортированы по обратному порядку даты создания (DDate), то есть первыми должны быть самые "свежие"


Созданы две хранимые процедуры. Параметр @rfirst - номер первой записи, @rcount - количество возвращаемых записей.


Способ 1. Обрезание результатов

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
CREATE PROCEDURE rn_top @rfirst int, @rcount int AS
set @rfirst=@rfirst+@rcount

SET ROWCOUNT @rfirst
select DDate,RowID into #temp from NTable
order by DDate desc

SET ROWCOUNT @rcount
select DDate,RowID from #temp
SET ROWCOUNT  0 

Способ 2. Усовершенствованное обрезание результатов
Скорость этого способа выше, так как
используется индекс по полю NDate, которое было заполнено следующим образом:
Код: plaintext
1.
Update NTable
set NDate = - convert(float,DDate)

В реальных приложениях его изменение надо проводить через тригер на вставку-изменение.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
CREATE PROCEDURE rnNd_top @rfirst int, @rcount int AS
set @rfirst=@rfirst+@rcount

SET ROWCOUNT @rfirst
select DDate,RowID into #temp from NTable
order by NDate

SET ROWCOUNT @rcount
select DDate,RowID from #temp
SET ROWCOUNT  0 
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034825
SM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а если сортировка может быть какой угодно - по возрастанию и убыванию, причем по любому из полей базового запроса ?
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034838
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А кто мешает поставить свой ORDER BY c любыми полями и их комбинациями? В способе 1 это не проблема. Для разных комбинаций полей можно наделать разных процедур.

Другое дело способ 2. Он конечно более специфический и требует создания дополнительного поля (полей) обратной сортировки, что легко делается только для числовых данных (включая Datetime). Приведен он главным образом для того, что бы показать, как правильно созданный индекс может увеличить скорость обработки.
Если бы в задаче не надо было бы сортировать даты по убыванию, то нужно было бы просто сделать индекс по DDate.

А вообще-то данная задача (возвращение N записей, начиная с M-той) порочна по своей сути. Пользователю возвращается не то, что ему нужно, а просто куча информации - пускай сам ищет что ему надо, а мы (разработчики), умываем руки. С этим можно смириться только в интернет-приложениях, типа форума, гостевой книги или чата.
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034854
Sanek
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Погодите !
Либо я не догоняю, либо все проще ...
если есть таблица (в примере от Cat2)
известна запись с которой надо начинать ... и кол-во строк ... то тогда можно зацепиться за поле RowID
т.е.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE PROCEDURE rnNd_top @rfirst int, @rcount int AS

SET ROWCOUNT @rcount 

select DDate,RowID 
where RowID < @rfirst 
order by NDate

SET ROWCOUNT  0 


Или я неправ ...
PS.
Какя разница (следить за номером строки или за ее кодом ?)
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034915
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Cat2
Glory, ау! У Вас была сделано такая штука, но я теперь хоть убей не могу ее найти.

Да где-то это затерялось при переезде форума. Если только админ сообщит номера топиков....

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

2Sanek
Какя разница (следить за номером строки или за ее кодом ?)

А если в RowID имеются "пробелы" ?
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034918
Sanek
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>Glory
в примере от Cat2
написанно на чистом SQL
Код: plaintext
[RowID] [int] IDENTITY ( 1 ,  1 ) 

, что в моем понимании есть автоинкрементное поле, т.е. Integer
Про пробелы в этом типе данных ничего не сказано , да и в номере строки пробел тоже наврядли появиться .. :)
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034925
fima
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я сегодня отвечал на похожий вопрос о нумерации. Для динамического количества выводимых строк, по моему их надо считать. /topic/9523 здесь примеры какие я знаю для нумерации строк, чуть изменить под данную задачу не трудно. Если поможет буду рад...
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034926
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"Пробелы" в поле identity могут получится при нормальной работе, например, в результате отакта транзакции
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
truncate table ntable
go
insert ntable values(GETDATE(),  1 )
select IDENT_CURRENT('ntable')
go
begin transaction
insert ntable values(GETDATE(),  1 )
rollback transaction
go
insert ntable values(GETDATE(),  1 )
select IDENT_CURRENT('ntable')
select * from ntable
go
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034929
Sanek
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
прошу прощения !
Понял !
Осознал ... и т.п.

Нашел ошибку и исправил :
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE PROCEDURE rnNd_top @rfirst int, @rcount int AS

SET ROWCOUNT @rcount 

select DDate,RowID 
where RowID > @rfirst 
order by NDate

SET ROWCOUNT  0 



В этом случае мало интересно пропуски индекса ... :)
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034936
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Cat2, Sanek

Не подумайте только, что я хочу на вас наехать, но ваши скрипты в предложенном варианте у меня возвращают всегда только первую "страницу"

Для большего правдоподобия я заполнил тестовую таблицу произвольными значениями RowId

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
truncate table ntable
go
SET IDENTITY_INSERT ntable ON
go
declare @i int, @j int
set @i =  10000 

while @i >  0 
begin
	set @i = @i -  1 
	if (@i %  3 ) =  0  
	begin
		set @j = CAST(RAND()* 100000  AS int)
		while @j <=  10000  or exists(select * from ntable where rowid = @j) set @j = CAST(RAND()* 100000  AS int)
	end
	else set @j = @i
	insert ntable(rowid, ddate) values(@j, DATEADD(dd, CAST(RAND()* 1000  AS int), GETDATE()))

end
go
SET IDENTITY_INSERT ntable OFF
go
Update NTable set NDate = - convert(float,DDate)
go
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32034939
Sanek
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>Glory

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
 Declare @RowNo integer,@RowCount integer
SET @RowCount =  10 
SET ROWCOUNT @RowCount
SET RowNo =  0 

SELECT *
  FROM ntable
WHERE RowID > @RowNo 
order by RowID

SET RowNo =  10 

SELECT *
  FROM ntable
WHERE RowID > @RowNo 
order by RowID

SET ROWCOUNT  0 

Попробовал совместно с твоим запросом и все работает нормально , только :) сортировку изменил с NDate на RowID
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32035020
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Данные примеры показывают способ работы с полем DDate, котрый не коррелирует с кластерным индексом по RowID. Такая корреляция обычно бывает, например, при оформлении каких-то докментов.

Значения DDate могут перманентно менятся. A'la время последнего ответа на вопрос в форуме, где RowID означает ID темы, a DDate обновляет тригер последнего постинга в эту тему.

Все, что выше этой строки, написано до полного разбора полетов.
Ну дела!!! Ну M$ наоптимизировал!
После издевательств над базой по методу Glory все любовно выписанное рухнуло. Плевал оказывается MS SQL на всякие там ордер бай при вставке во временные таблицы. И моя вера в физическое расположение записей по кластерному индексу сильно подорвана. Может быть по этому поводу выскажется кто-нибудь из DBA? У меня такое подозрение, что после столь крутых изменений первичного ключа таблицу надо как-то оптимизировать.

"Орешек знаний тверд, но все же мы не привыкли отступать..."

А как Вам такое извращение?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
CREATE PROCEDURE rnd_top @rfirst int, @rcount int AS
set @rfirst=@rfirst+@rcount

SET ROWCOUNT @rfirst
select DDate,RowID  into #temp from NTable
order by DDate desc

SET ROWCOUNT @rcount
select  DDate,RowID into #temp2 from #temp
order by DDate 

select  DDate,RowID from #temp2
order by DDate desc
SET ROWCOUNT  0 


С полем NDate ничего пока не придумал. Не работает ни под каким соусом.
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32035024
Vit!
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plaintext
1.
select top  100  * from 
  (Select top  200  * From MyTable) as T
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32035027
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Re Vit!

В обороте TOP нельзя использовать переменные.
Вы не обратили внимание, что надо сортировать по возрастанию даты, а не по кластерному индексу.

Конечно, можно использовать динамический SQL, но при более сложных выборках это будет тормозить.

Если Вам не лень, попробуйте свой пример на вышеприведенной тестовой таблице, обработаной по методу GLory.
Мне честно говоря, сегодня лень.

Кстати, на моей памяти, это не то тридцатое, не то сороковое предложение данного способа. Наверное, что-то тут не то, если он так и не стал каноническим.
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32035036
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я в постинге от 20020703 20:03 несколько запутанно выразился. Данная задача призвана решить некоррелированные с PRIMARY выборки. Разговор про документы является примером коррелированных данных.
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32035038
Vit!
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
To: Cat2
Сорри, я собственно отвечал на самый первый заданный вопрос, не особенно вникая в суть обсуждения и предложенные варианты, так что звиняйте что не в тему. Попробовать пока могу только теоретически - у меня тут полная неразбериха с Update серверов. По поводу методов могу сказать что реально вижу только 2 алгоритма реализации (глобально, без разницы через как это будет конкретно реализовано, сколько запросов/подзапросов/View/процедур будет вовлечено):

1. Или записи нумеруются (в таблице, во временной таблице, во View еще бог знает где) и выполняется Select уже по номеру
2. Или кверится больше и затем опять кверится в инверсивном порядке (здесь - сорри, допустил ошибку в приведенном ранее коде, надо было обратную сортировку задать)
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32035041
Фотография Cat2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Для VIT!.

Вы совершенно правы в определении области решений. Но к сожалению, "чистое" решение эти вопросов упирается в конкретные реализации на конкретных серверах и таблицах.

Правда есть еще одно решение, принадлежащие Ron Soukap, ведущему разработчику MS 6.5. Я все более и более склоняюсь к мысли, что только оно корректно работает всегда и везде.

Его главный смысл - дополнительное поле нумерации и заполнение его через UPDATE.
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32035053
Vit!
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну в общем и я к тому же - наиболее корректно (точнее быстро) будет работать нумерация...
...
Рейтинг: 0 / 0
Вот такой вопрос !
    #32035073
Sanek
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Возвращаясь к нашим баранам остаеться последний (на мой взгляд) общий вариант такого выбора :
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
DECLARE @FROM INT,
	@COUNT INT

SET @FROM =  10 
SET @COUNT =  10 

CREATE TABLE #TEMP 
(
Rank INTEGER IDENTITY( 1 , 1 ) ,
DDate DateTime,
NDatу float 
)

insert inTO #TEMP
Select t1.DDate,
       t1.NDate 
 --  inTo #Temp
 
  from NTable as T1
order by t1.DDate

SET ROWCOUNT @COUNT
Select * from #Temp
WHERE Rank > @FROM

drop table #TEMP

как мне кажеться такой вариант подходит под любую сортировку ...
...
Рейтинг: 0 / 0
29 сообщений из 29, показаны все 2 страниц
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Вот такой вопрос !
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]