Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Запрос для получения данных  [new]
harisma
Member

Откуда:
Сообщений: 243
Необходимо переделать скрипт для получения части данных из таблицы, чтобы корректно работал.
Существует проект в архитектуре клиент-сервер. Связь между клиентской и серверной стороной реализована через TProvider, то есть, на серверной стороне для получения данных из MS SQL Server используется компонента TADODataSet, а на клиенте - TClientDataSet, связанный с TADODataSet через компоненту провайдера. Но не в том суть. А в том, что данные на клиента передаются фреймами регулируемой величины, то есть, на сервере поднимается не вся таблица с данными, а только ее часть.
На данный момент логика построения скрипта для поднятия данных на сервере следующая:
- с клиента на сервер передается идентификатор текущей записи (ключевое поле, идентифицирующее запись в таблице, носит имя RecID)
- также, с клиента на сервер передаются параметры фильтрации записей в запросе, поле, по которому следует отсортировать результирующий набор данных и направление сортировки.
- на сервере в зависимости от направления сортировки относительно переданного идентификатора записи, делается выборка размером в половину размера фрейма с направлением сортировки ОБРАТНОМ от переданного с клиента и фиксируется значение идентификатора последней записи в полученной выборке.
- после этого, строится выборка с количеством записей равном размеру фрейма уже с нужным направлением сортировки, начиная с идентификатора записи, зафиксированного на предыдущем шаге.
- эта выборка и передается на клиента через провайдера (технология Midas).
- согласно задумки авторов данной логики, текущая запись, идентификатор которой передавался на сервер на первом шаге, обязательно будет в результирующей выборке. И она будет в середине полученной выборки.
- на эту запись помещается текущая позиция курсора в TClientDataSet на клиенте.

И все в этой логике хорошо и гладко, за исключением одного НО! Если сортировка устанавливается по полю, в котором есть много значений NULL, то результирующая выборка не будет детерминированной, то есть при каждом запросе набор данных, попавший в него, будет разный :(
Поэтому возникает вопрос, как переделать существующую логику, чтобы:
- результирующая выборка была детерминированной
- скорость получения данных на клиенте не упала.

Нами перепробованы уже несколько вариантов решения:
- добавление калькулируемой колонки со значениями из колонки, по которой необходимо делать сортировку, на которые наложено условие IsNull и результирующая сортировка делается уже по этой колонке - но это сильно затормозило процесс получения данных клиентом
- включение в запрос хранимой процедурки, которая производит вычисление количества данных ДО и ПОСЛЕ указанной записи при построении запроса и уже на этих данных строится результирующий запрос - но этот вариант тоже оказался медленным на 20-50% от существующего, поэтому начальство его тоже забраковало. :(

Что подскажете?

Если это текстовое описание не очень понятно - могу показать существующий скрипт и скрипт с хранимой процедуркой (скрипт с калькулируемым полем не сохранился к сожалению)
12 ноя 13, 18:49    [15117634]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
Glory
Member

Откуда:
Сообщений: 104751
harisma
И все в этой логике хорошо и гладко, за исключением одного НО! Если сортировка устанавливается по полю, в котором есть много значений NULL, то результирующая выборка не будет детерминированной, то есть при каждом запросе набор данных, попавший в него, будет разный :(
Поэтому возникает вопрос, как переделать существующую логику, чтобы:
- результирующая выборка была детерминированной
- скорость получения данных на клиенте не упала.

Сортировать еще и по ПК
12 ноя 13, 18:54    [15117653]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
harisma
Member

Откуда:
Сообщений: 243
Glory
Сортировать еще и по ПК

Так по нему тоже сортируется. Только это не помогает :(
12 ноя 13, 18:57    [15117665]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
Glory
Member

Откуда:
Сообщений: 104751
harisma
Так по нему тоже сортируется. Только это не помогает :(

NULL, PK
NULL, PK
дают гарантированный порядок сортировки
12 ноя 13, 19:01    [15117684]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
harisma
Member

Откуда:
Сообщений: 243
Все-таки наверно лучше показать скрипт. Он такой:
declare @id char(16), @reccount int
set @id='B04F638E491FB240'
declare @Str varchar(70)
declare @P1 int
select @Str = D.NAME from Dictionaries_C3AD665D2FD8E140 as D where ((D.HASCHILD = 0)) and (D.recid = @ID)

set @reccount=@@ROWCOUNT
set @Str = IsNull(@Str, '')
if (@reccount <> 0) begin
	declare cur cursor local scroll for
	select top 10 D.NAME, D.recid from Dictionaries_C3AD665D2FD8E140 as D
	where ((D.HASCHILD = 0)) and ((IsNull(D.NAME, '') < @Str) or ((IsNull(D.NAME, '') = @Str) and (D.recid <= @ID)))
	order by D.NAME desc, D.recid desc
	open cur
	fetch last from cur into @Str, @ID
	  set @P1 = @@CURSOR_ROWS
    close cur
    deallocate cur
	set @Str = IsNull(@Str, '')
	select top 20 D.RECTYPE,D.RECID,D.HASCHILD,D.PARENTID,D.LINKTYPE,D.LINKID,D.USERSAVEID,D.SAVETS,D.CODE,D.NAME,
	D.F3,D.F2,D.F16,D.F77,D.F5,D.F4,D.F17,D.F8,D.F9,D.F10,D.F11,D.F13,F15=convert(decimal(28,5),0),
	F18=convert(decimal(28,5),0),D.F19,D.F21,D.F22,D.F23,D.F24,D.F25,D.F26,D.F27,D.F28,D.F29,D.F30,D.F32,D.F44,
	F33=convert(decimal(28,5),0) FROM Dictionaries_C3AD665D2FD8E140 AS D WITH(INDEX(NAME))
	where ((D.HASCHILD = 0)) and ((IsNull(D.NAME, '') > @Str) or ((IsNull(D.NAME, '') = @Str) and (D.recid >= @ID)))
	order by D.NAME asc, D.recid asc
end else
	select top 20 D.RECTYPE,D.RECID,D.HASCHILD,D.PARENTID,D.LINKTYPE,D.LINKID,D.USERSAVEID,D.SAVETS,D.CODE,D.NAME,
	D.F3,D.F2,D.F16,D.F77,D.F5,D.F4,D.F17,D.F8,D.F9,D.F10,D.F11,D.F13,F15=convert(decimal(28,5),0),
	F18=convert(decimal(28,5),0),D.F19,D.F21,D.F22,D.F23,D.F24,D.F25,D.F26,D.F27,D.F28,D.F29,D.F30,D.F32,D.F44,
	F33=convert(decimal(28,5),0) FROM Dictionaries_C3AD665D2FD8E140 AS D WITH(INDEX(NAME))
	where ((D.HASCHILD = 0))
	order by D.NAME asc, D.recid asc


Примари кей у таблицы Dictionaries_C3AD665D2FD8E140 состоит из полей RecID и RecType, причем в поле RecType всегда пишется одинаковое значение, потому можно наверно этим полем в запросе пренебречь.
Размер фрейма установлен в 20 записей.
Поле сортировки - NAME; Направление сортировки - A-Z
12 ноя 13, 19:30    [15117766]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
Glory
Member

Откуда:
Сообщений: 104751
harisma
Все-таки наверно лучше показать скрипт. Он такой:

И вы утвержаете, что при order by ... D.recid "результирующая выборка не будет детерминированной, то есть при каждом запросе набор данных, попавший в него, будет разный " ?
12 ноя 13, 22:34    [15118276]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
harisma
Member

Откуда:
Сообщений: 243
Glory
И вы утвержаете, что при order by ... D.recid "результирующая выборка не будет детерминированной, то есть при каждом запросе набор данных, попавший в него, будет разный " ?

Да, утверждаю. Только маленькое уточнение: Набор данных в результирующем наборе при сортировке в РАЗНЫЕ стороны будет разный, а не просто при каждом запросе. В том то и проблема, что сначала сортируется в одном направлении, запоминается позиция, а потом сортируется в другом направлении. После сортировки результирующий набор должен быть спозиционирован на эту позицию, а оказывается, что она или смещенная, или ее вообще не окажется в результирующем наборе. Я понятно объяснил суть?
13 ноя 13, 11:08    [15119892]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
Glory
Member

Откуда:
Сообщений: 104751
harisma
Да, утверждаю. Только маленькое уточнение: Набор данных в результирующем наборе при сортировке в РАЗНЫЕ стороны будет разный

Офигеть просто какое несущественное уточнение. Только причем тут " много значений NULL", если меняется список полей в сортировке ?

harisma
В том то и проблема, что сначала сортируется в одном направлении, запоминается позиция, а потом сортируется в другом направлении. После сортировки результирующий набор должен быть спозиционирован на эту позицию, а оказывается, что она или смещенная, или ее вообще не окажется в результирующем наборе.

Смена сортировки означает _другой_ запрос. Зачем позиционировать на запись из предыдущего запроса ?

Сообщение было отредактировано: 13 ноя 13, 11:13
13 ноя 13, 11:12    [15119923]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
harisma
Member

Откуда:
Сообщений: 243
Glory
если меняется список полей в сортировке ?

С чего вы взяли, что список полей в сортировке меняется? Список полей в СОРТИРОВКЕ тот же. Меняется только направление.
А разве при смене направления порядок записей в результирующем наборе не должен поменяться на точно противоположный? Я вижу на практике. что при NULL значениях это не происходит к сожалению :(. Особенно если намешаны в этом поле (по которому выполняется сортировка) NULL и пустые строки (если поле текстовое)

Glory
Смена сортировки означает _другой_ запрос. Зачем позиционировать на запись из предыдущего запроса ?

Такова логика получения и отображения данных в проекте. А каким образом это можно сделать по другому?
13 ноя 13, 11:23    [15120025]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
Glory
Member

Откуда:
Сообщений: 104751
harisma
Список полей в СОРТИРОВКЕ тот же. Меняется только направление.

Один фиг.
harisma
А разве при смене направления порядок записей в результирующем наборе не должен поменяться на точно противоположный? Я вижу на практике. что при NULL значениях это не происходит к сожалению

Почините свою "практику" ?

declare @t table(id int, f1 varchar(10))

insert @t values(1, 'A')
insert @t values(2, 'NULL')
insert @t values(3, 'B')
insert @t values(4, 'NULL')

select * from @t order by f1 asc, id
select * from @t order by f1 desc, id desc
13 ноя 13, 11:31    [15120104]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
harisma
Member

Откуда:
Сообщений: 243
Glory
Почините свою "практику" ?

declare @t table(id int, f1 varchar(10))

insert @t values(1, 'A')
insert @t values(2, 'NULL')
insert @t values(3, 'B')
insert @t values(4, 'NULL')

select * from @t order by f1 asc, id
select * from @t order by f1 desc, id desc


'NULL'
?????
Я имел ввиду вовсе не это. В моем случае имеем в таблице в поле значение NULL без кавычек, то есть отсутствие значения, а не строку со значением 'NULL'
13 ноя 13, 11:36    [15120151]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
Glory
Member

Откуда:
Сообщений: 104751
harisma
Я имел ввиду вовсе не это. В моем случае имеем в таблице в поле значение NULL без кавычек, то есть отсутствие значения, а не строку со значением 'NULL'

Вы просто фейспалм какой-то
declare @t table(id int, f1 varchar(10))

insert @t values(1, 'A')
insert @t values(2, NULL)
insert @t values(3, 'B')
insert @t values(4, NULL)

select * from @t order by f1 asc, id
select * from @t order by f1 desc, id desc
13 ноя 13, 11:37    [15120166]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
harisma
Member

Откуда:
Сообщений: 243
Ладно, наверно без реального примера возвращенных данных, объяснить не получится. Щас, в SSMS на реальных данных по частям вышеприведенный скрипт выполню и покажу, что получилось, и что ожидалось получить.
13 ноя 13, 11:40    [15120183]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
Glory
Member

Откуда:
Сообщений: 104751
harisma
Щас, в SSMS на реальных данных по частям вышеприведенный скрипт выполню и покажу, что получилось, и что ожидалось получить.

Привидите такой же пример. Который каждый сможет выполнить у себя.
13 ноя 13, 11:41    [15120198]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
harisma
Member

Откуда:
Сообщений: 243
Итак, идем по порядку. У меня в таблице Dictionaries_C3AD665D2FD8E140 находится 123 записи.
Содержимое таблицы:
RECIDCODENAMERECTYPE
E8066E99351FB240NULL1C3AD665D2FD8E140
F895FB65621FB240NULL10C3AD665D2FD8E140
A0EDF0DE0A1FB240NULL100C3AD665D2FD8E140
30D0F4D49D1FB240NULL11C3AD665D2FD8E140
C06937527F1FB240NULL12C3AD665D2FD8E140
7890E8714D1FB240NULL13C3AD665D2FD8E140
683814C5961FB240NULL14C3AD665D2FD8E140
784D3E7ED91EB240NULL15C3AD665D2FD8E140
F0663CB4891FB240NULL17C3AD665D2FD8E140
B829CB98891FB240NULL18C3AD665D2FD8E140
D057AC0FF21EB240NULL19C3AD665D2FD8E140
20D389C0E61EB240NULL2C3AD665D2FD8E140
C067DF33E51EB240NULL20C3AD665D2FD8E140
3844D013BC1EB240NULL21C3AD665D2FD8E140
E021BF9B591FB240NULL22C3AD665D2FD8E140
800F409E991FB240NULL23C3AD665D2FD8E140
D85663425E1FB240NULL24C3AD665D2FD8E140
10F9C87E4E1FB240NULL25C3AD665D2FD8E140
0055C524471FB240NULL26C3AD665D2FD8E140
E8804A4CBB1EB240NULL27C3AD665D2FD8E140
A01347733E1FB240NULL28C3AD665D2FD8E140
D0019D2E8F1FB240NULL29C3AD665D2FD8E140
1003E220091FB240NULL3C3AD665D2FD8E140
68F70603D51EB240NULL30C3AD665D2FD8E140
285A62958F1FB240NULL31C3AD665D2FD8E140
18FA4760B41EB240NULL32C3AD665D2FD8E140
F809F6138C1FB240NULL33C3AD665D2FD8E140
20A8D899C11EB240NULL34C3AD665D2FD8E140
48DE4ADAE91EB240NULL35C3AD665D2FD8E140
1019601D2A1FB240NULL36C3AD665D2FD8E140
B892BC82851FB240NULL37C3AD665D2FD8E140
9812D43CF41EB240NULL38C3AD665D2FD8E140
60F90B2D4B1FB240NULL39C3AD665D2FD8E140
E06180E5E31EB240NULL4C3AD665D2FD8E140
48F9C634D31EB240NULL40C3AD665D2FD8E140
78B71F1EA41EB240NULL41C3AD665D2FD8E140
F8CBD5CBBA1EB240NULL42C3AD665D2FD8E140
2886F65C861FB240NULL43C3AD665D2FD8E140
20FEF8E2101FB240NULL44C3AD665D2FD8E140
C8578204DE1EB240NULL45C3AD665D2FD8E140
00F2F58EF31EB240NULL46C3AD665D2FD8E140
40C08E42011FB240NULL47C3AD665D2FD8E140
7892B192E81EB240NULL48C3AD665D2FD8E140
4815963B371FB240NULL49C3AD665D2FD8E140
F01A933C631FB240NULL5C3AD665D2FD8E140
10589652FF1EB240NULL50C3AD665D2FD8E140
48F2AA4BDF1EB240NULL51C3AD665D2FD8E140
1891F198081FB240NULL52C3AD665D2FD8E140
208A4D5CC91EB240NULL53C3AD665D2FD8E140
88BD54C3971FB240NULL54C3AD665D2FD8E140
103A5347A11FB240NULL55C3AD665D2FD8E140
486CF330171FB240NULL56C3AD665D2FD8E140
A8C7CB7E3E1FB240NULL57C3AD665D2FD8E140
B0940B0AE61EB240NULL58C3AD665D2FD8E140
18ECD571061FB240NULL59C3AD665D2FD8E140
70FF2DC1CA1EB240NULL6C3AD665D2FD8E140
70E334B8471FB240NULL60C3AD665D2FD8E140
C0E68666AB1EB240NULL61C3AD665D2FD8E140
A02ADAA7751FB240NULL62C3AD665D2FD8E140
9046C4C03A1FB240NULL63C3AD665D2FD8E140
800A762A721FB240NULL64C3AD665D2FD8E140
207026EEF41EB240NULL65C3AD665D2FD8E140
10AC1692DF1EB240NULL66C3AD665D2FD8E140
18CDDF6E9E1FB240NULL67C3AD665D2FD8E140
E887AADD281FB240NULL68C3AD665D2FD8E140
380F94B32C1FB240NULL69C3AD665D2FD8E140
386606009F1FB240NULL7C3AD665D2FD8E140
B04F638E491FB240NULL70C3AD665D2FD8E140
E0753CC8B21EB240NULL71C3AD665D2FD8E140
E88A157E881FB240NULL72C3AD665D2FD8E140
683B0004911FB240NULL73C3AD665D2FD8E140
A00198CE151FB240NULL74C3AD665D2FD8E140
180A2036F81EB240NULL75C3AD665D2FD8E140
98562A4ABE1EB240NULL76C3AD665D2FD8E140
D028D0071C1FB240NULL77C3AD665D2FD8E140
48C9CFCC5E1FB240NULL78C3AD665D2FD8E140
086C1A8BC91EB240NULL79C3AD665D2FD8E140
7058E252281FB240NULL8C3AD665D2FD8E140
10E1AC8E801FB240NULL80C3AD665D2FD8E140
D0F7B82ECE1EB240NULL81C3AD665D2FD8E140
D0406D671B1FB240NULL82C3AD665D2FD8E140
F812FC8E801FB240NULL83C3AD665D2FD8E140
78C49F62F51EB240NULL84C3AD665D2FD8E140
60D0C2DB1F1FB240NULL85C3AD665D2FD8E140
4834273D071FB240NULL86C3AD665D2FD8E140
8867EBCA6F1FB240NULL87C3AD665D2FD8E140
F8FB4CA3C31EB240NULL88C3AD665D2FD8E140
B0F2DB50461FB240NULL89C3AD665D2FD8E140
3033E77DD11EB240NULL9C3AD665D2FD8E140
D8309F48AB1EB240NULL90C3AD665D2FD8E140
48B1F5947D1FB240NULL91C3AD665D2FD8E140
605F00304A1FB240NULL92C3AD665D2FD8E140
78A3CB5C6C1FB240NULL95C3AD665D2FD8E140
98C98E66391FB240NULL96C3AD665D2FD8E140
783ECA21781FB240NULL98C3AD665D2FD8E140
58022D371C1FB240NULL99C3AD665D2FD8E140
28994C06571FB040NULLdbgdfdfbdfdf dfg dgddghdhgh fgtghtrtrtrhtry trtrytrC3AD665D2FD8E140
F0340536F066B340NULLdgdfdfgdfgdffgghC3AD665D2FD8E140
10E47A63B209B240NULLggggggC3AD665D2FD8E140
804C4D5BFA66B340NULLkljkluikkC3AD665D2FD8E140
08D91CBE221FB240ghjghkhh k.io;iop;ioC3AD665D2FD8E140
6017E922491FB240hkyuiyujki78ouiC3AD665D2FD8E140
1078D9506F1FB240iuopuiuipio[ioC3AD665D2FD8E140
7057D816531FB240jhkluiooyuererterteytrC3AD665D2FD8E140
08C58210A61EB240klkj;;kl'opklhjghgfhgfC3AD665D2FD8E140
689A1DD90F1FB240liopp980[9p[pio[op[p[iop[]C3AD665D2FD8E140
B01EC81B961FB240p[p;l;l;l;k;klk;;kpiC3AD665D2FD8E140
68C3DEE9DF1EB240wereqwqwtwetyrweerwC3AD665D2FD8E140
60131E0A484BB34012111111212Їстивний засібC3AD665D2FD8E140
986D6C12568CB1401234356789123456789C3AD665D2FD8E140
D046F5C48E44B040123456dffgdfgdghdtC3AD665D2FD8E140
801E376C2C1FB2401616161616C3AD665D2FD8E140
D0A5B75B1B00AA4020234234sdfsdweC3AD665D2FD8E140
E076597B4C2DAD4044444444444444aaaaaamC3AD665D2FD8E140
F0B6E4589DDDA94045446fgdfdfdC3AD665D2FD8E140
40F617CF45FBA94055556788Тестовый товар 111C3AD665D2FD8E140
68A29063791FB240565575fthtrtrtrtrutrC3AD665D2FD8E140
A09043BB8FAFB14064578946556пгоонгпC3AD665D2FD8E140
E8BD0547247EB1406678878yuytutiyui7iyuC3AD665D2FD8E140
58A084409B1FB240675697C3AD665D2FD8E140
E8EC4943191FB2406756uijmnmghhjljklhjkhjC3AD665D2FD8E140
104F19CF2329B340hjgfhgfhgfhgfgfutesttesttestC3AD665D2FD8E140
187765541D18B240jk789978hjkjlljil;hjC3AD665D2FD8E140

Выполняем первую часть скрипта:
declare @id char(16), @reccount int
set @id='1078D9506F1FB240'
declare @Str varchar(70)
select @Str = D.CODE from Dictionaries_C3AD665D2FD8E140 as D where (D.recid = @ID)

set @reccount=@@ROWCOUNT
set @Str = IsNull(@Str, '')
select @Str, @reccount


Результат:
(No column name) (No column name)
1
(как видно из содержимого таблицы, значение поля CODE для этой записи - пустая строка (не NULL))

Поскольку @reccount = 1, условие if будет истинным - идем по ветке, где @reccount <> 0:
    declare cur cursor local scroll for
    select top 10 D.CODE, D.recid from Dictionaries_C3AD665D2FD8E140 as D
    where ((IsNull(D.CODE, '') < @Str) or ((IsNull(D.CODE, '') = @Str) and (D.recid <= @ID)))
    order by D.CODE desc, D.recid desc
    open cur
    declare @P1 int
	fetch last from cur into @Str, @ID
	  set @P1 = @@CURSOR_ROWS
    close cur
    deallocate cur
    set @Str = IsNull(@Str, '')
    select @P1, @str


Результат (покажу набор данных, возвращаемых курсором, и собственно значения переменных, которые нужны для дальнейшей работы):
CODErecid
1078D9506F1FB240
08D91CBE221FB240
08C58210A61EB240
NULL10589652FF1EB240
NULL103A5347A11FB240
NULL1019601D2A1FB240
NULL1003E220091FB240
NULL086C1A8BC91EB240
NULL 00F2F58EF31EB240
NULL0055C524471FB240

(No column name) (No column name)
10


и финальная часть скрипта:
    select top 20 D.RECTYPE,D.RECID,D.CODE,D.NAME
    FROM Dictionaries_C3AD665D2FD8E140 AS D WITH(INDEX(CODE))
    where ((IsNull(D.CODE, '') > @Str) or ((IsNull(D.CODE, '') = @Str) and (D.recid >= @ID)))
    order by D.CODE asc, D.recid asc


Ее результат:
RECTYPERECIDCODENAME
C3AD665D2FD8E1400055C524471FB240NULL26
C3AD665D2FD8E14000F2F58EF31EB240NULL46
C3AD665D2FD8E140086C1A8BC91EB240NULL79
C3AD665D2FD8E1401003E220091FB240NULL3
C3AD665D2FD8E1401019601D2A1FB240NULL36
C3AD665D2FD8E140103A5347A11FB240NULL55
C3AD665D2FD8E14010589652FF1EB240NULL50
C3AD665D2FD8E14010AC1692DF1EB240NULL66
C3AD665D2FD8E14010E1AC8E801FB240NULL80
C3AD665D2FD8E14010E47A63B209B240NULLgggggg
C3AD665D2FD8E14010F9C87E4E1FB240NULL25
C3AD665D2FD8E140180A2036F81EB240NULL75
C3AD665D2FD8E1401891F198081FB240NULL52
C3AD665D2FD8E14018CDDF6E9E1FB240NULL67
C3AD665D2FD8E14018ECD571061FB240NULL59
C3AD665D2FD8E14018FA4760B41EB240NULL32
C3AD665D2FD8E140207026EEF41EB240NULL65
C3AD665D2FD8E140208A4D5CC91EB240NULL53
C3AD665D2FD8E14020A8D899C11EB240NULL34
C3AD665D2FD8E14020D389C0E61EB240NULL2


Ожидалось, что 10 запись в полученной выборке будет иметь значение RECID = 1078D9506F1FB240, указанное в первой части скрипта, то есть, с чего начиналось построение скрипта. На эту запись на клиентской стороне, как я описывал в первом своем посте в данной теме, и должен быть спозиционирован TClientDataSet. Но, как видно из результата запроса, запись с номером 10 имеет другое значение в поле RECID, а именно 10E47A63B209B240, а запись с RECID = 1078D9506F1FB240 вообще не попала в данную выборку. Причину я вижу в том, что набор данных в курсоре включает в себя по сортируемому полю и пустые и NULL значения. Поэтому, когда меняем направление сортировки, пустые значения уже не попадают в выборку.

Вроде теперь полностью описал и проиллюстрировал проблему.
13 ноя 13, 13:01    [15120904]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
Glory
Member

Откуда:
Сообщений: 104751
harisma
Вроде теперь полностью описал и проиллюстрировал проблему.

И что вы предлагаете другим сделать с предложенными вами "сккриншотами" данных и фрагментами кода ?
13 ноя 13, 13:08    [15120983]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
harisma
Member

Откуда:
Сообщений: 243
Вот скрипт на создание таблицы:
CREATE TABLE [dbo].[Dictionaries_C3AD665D2FD8E140](
	[RECID] [varchar](16) NOT NULL,
	[code] [varchar](20) NULL,
	[NAME] [varchar](70) NULL,
	[RECTYPE] [char](16) NOT NULL,
 CONSTRAINT [PK_Dictionaries_C3AD665D2FD8E140] PRIMARY KEY CLUSTERED 
(
	[RECID] ASC,
	[RECTYPE] ASC
)) ON [PRIMARY]


теперь заполним ее данными:
insert into dbo.[Dictionaries_C3AD665D2FD8E140]
values ('E8066E99351FB240',NULL,'1','C3AD665D2FD8E140'),
('F895FB65621FB240',NULL,'10','C3AD665D2FD8E140'),
('A0EDF0DE0A1FB240',NULL,'100','C3AD665D2FD8E140'),
('30D0F4D49D1FB240',NULL,'11','C3AD665D2FD8E140'),
('C06937527F1FB240',NULL,'12','C3AD665D2FD8E140'),
('7890E8714D1FB240',NULL,'13','C3AD665D2FD8E140'),
('683814C5961FB240',NULL,'14','C3AD665D2FD8E140'),
('784D3E7ED91EB240',NULL,'15','C3AD665D2FD8E140'),
('F0663CB4891FB240',NULL,'17','C3AD665D2FD8E140'),
('B829CB98891FB240',NULL,'18','C3AD665D2FD8E140'),
('D057AC0FF21EB240',NULL,'19','C3AD665D2FD8E140'),
('20D389C0E61EB240',NULL,'2','C3AD665D2FD8E140'),
('C067DF33E51EB240',NULL,'20','C3AD665D2FD8E140'),
('3844D013BC1EB240',NULL,'21','C3AD665D2FD8E140'),
('E021BF9B591FB240',NULL,'22','C3AD665D2FD8E140'),
('800F409E991FB240',NULL,'23','C3AD665D2FD8E140'),
('D85663425E1FB240',NULL,'24','C3AD665D2FD8E140'),
('10F9C87E4E1FB240',NULL,'25','C3AD665D2FD8E140'),
('0055C524471FB240',NULL,'26','C3AD665D2FD8E140'),
('E8804A4CBB1EB240',NULL,'27','C3AD665D2FD8E140'),
('A01347733E1FB240',NULL,'28','C3AD665D2FD8E140'),
('D0019D2E8F1FB240',NULL,'29','C3AD665D2FD8E140'),
('1003E220091FB240',NULL,'3','C3AD665D2FD8E140'),
('68F70603D51EB240',NULL,'30','C3AD665D2FD8E140'),
('285A62958F1FB240',NULL,'31','C3AD665D2FD8E140'),
('18FA4760B41EB240',NULL,'32','C3AD665D2FD8E140'),
('F809F6138C1FB240',NULL,'33','C3AD665D2FD8E140'),
('20A8D899C11EB240',NULL,'34','C3AD665D2FD8E140'),
('48DE4ADAE91EB240',NULL,'35','C3AD665D2FD8E140'),
('1019601D2A1FB240',NULL,'36','C3AD665D2FD8E140'),
('B892BC82851FB240',NULL,'37','C3AD665D2FD8E140'),
('9812D43CF41EB240',NULL,'38','C3AD665D2FD8E140'),
('60F90B2D4B1FB240',NULL,'39','C3AD665D2FD8E140'),
('E06180E5E31EB240',NULL,'4','C3AD665D2FD8E140'),
('48F9C634D31EB240',NULL,'40','C3AD665D2FD8E140'),
('78B71F1EA41EB240',NULL,'41','C3AD665D2FD8E140'),
('F8CBD5CBBA1EB240',NULL,'42','C3AD665D2FD8E140'),
('2886F65C861FB240',NULL,'43','C3AD665D2FD8E140'),
('20FEF8E2101FB240',NULL,'44','C3AD665D2FD8E140'),
('C8578204DE1EB240',NULL,'45','C3AD665D2FD8E140'),
('00F2F58EF31EB240',NULL,'46','C3AD665D2FD8E140'),
('40C08E42011FB240',NULL,'47','C3AD665D2FD8E140'),
('7892B192E81EB240',NULL,'48','C3AD665D2FD8E140'),
('4815963B371FB240',NULL,'49','C3AD665D2FD8E140'),
('F01A933C631FB240',NULL,'5','C3AD665D2FD8E140'),
('10589652FF1EB240',NULL,'50','C3AD665D2FD8E140'),
('48F2AA4BDF1EB240',NULL,'51','C3AD665D2FD8E140'),
('1891F198081FB240',NULL,'52','C3AD665D2FD8E140'),
('208A4D5CC91EB240',NULL,'53','C3AD665D2FD8E140'),
('88BD54C3971FB240',NULL,'54','C3AD665D2FD8E140'),
('103A5347A11FB240',NULL,'55','C3AD665D2FD8E140'),
('486CF330171FB240',NULL,'56','C3AD665D2FD8E140'),
('A8C7CB7E3E1FB240',NULL,'57','C3AD665D2FD8E140'),
('B0940B0AE61EB240',NULL,'58','C3AD665D2FD8E140'),
('18ECD571061FB240',NULL,'59','C3AD665D2FD8E140'),
('70FF2DC1CA1EB240',NULL,'6','C3AD665D2FD8E140'),
('70E334B8471FB240',NULL,'60','C3AD665D2FD8E140'),
('C0E68666AB1EB240',NULL,'61','C3AD665D2FD8E140'),
('A02ADAA7751FB240',NULL,'62','C3AD665D2FD8E140'),
('9046C4C03A1FB240',NULL,'63','C3AD665D2FD8E140'),
('800A762A721FB240',NULL,'64','C3AD665D2FD8E140'),
('207026EEF41EB240',NULL,'65','C3AD665D2FD8E140'),
('10AC1692DF1EB240',NULL,'66','C3AD665D2FD8E140'),
('18CDDF6E9E1FB240',NULL,'67','C3AD665D2FD8E140'),
('E887AADD281FB240',NULL,'68','C3AD665D2FD8E140'),
('380F94B32C1FB240',NULL,'69','C3AD665D2FD8E140'),
('386606009F1FB240',NULL,'7','C3AD665D2FD8E140'),
('B04F638E491FB240',NULL,'70','C3AD665D2FD8E140'),
('E0753CC8B21EB240',NULL,'71','C3AD665D2FD8E140'),
('E88A157E881FB240',NULL,'72','C3AD665D2FD8E140'),
('683B0004911FB240',NULL,'73','C3AD665D2FD8E140'),
('A00198CE151FB240',NULL,'74','C3AD665D2FD8E140'),
('180A2036F81EB240',NULL,'75','C3AD665D2FD8E140'),
('98562A4ABE1EB240',NULL,'76','C3AD665D2FD8E140'),
('D028D0071C1FB240',NULL,'77','C3AD665D2FD8E140'),
('48C9CFCC5E1FB240',NULL,'78','C3AD665D2FD8E140'),
('086C1A8BC91EB240',NULL,'79','C3AD665D2FD8E140'),
('7058E252281FB240',NULL,'8','C3AD665D2FD8E140'),
('10E1AC8E801FB240',NULL,'80','C3AD665D2FD8E140'),
('D0F7B82ECE1EB240',NULL,'81','C3AD665D2FD8E140'),
('D0406D671B1FB240',NULL,'82','C3AD665D2FD8E140'),
('F812FC8E801FB240',NULL,'83','C3AD665D2FD8E140'),
('78C49F62F51EB240',NULL,'84','C3AD665D2FD8E140'),
('60D0C2DB1F1FB240',NULL,'85','C3AD665D2FD8E140'),
('4834273D071FB240',NULL,'86','C3AD665D2FD8E140'),
('8867EBCA6F1FB240',NULL,'87','C3AD665D2FD8E140'),
('F8FB4CA3C31EB240',NULL,'88','C3AD665D2FD8E140'),
('B0F2DB50461FB240',NULL,'89','C3AD665D2FD8E140'),
('3033E77DD11EB240',NULL,'9','C3AD665D2FD8E140'),
('D8309F48AB1EB240',NULL,'90','C3AD665D2FD8E140'),
('48B1F5947D1FB240',NULL,'91','C3AD665D2FD8E140'),
('605F00304A1FB240',NULL,'92','C3AD665D2FD8E140'),
('78A3CB5C6C1FB240',NULL,'95','C3AD665D2FD8E140'),
('98C98E66391FB240',NULL,'96','C3AD665D2FD8E140'),
('783ECA21781FB240',NULL,'98','C3AD665D2FD8E140'),
('58022D371C1FB240',NULL,'99','C3AD665D2FD8E140'),
('28994C06571FB040',NULL,'dbgdfdfbdfdf dfg dgddghdhgh','C3AD665D2FD8E140'),
('F0340536F066B340',NULL,'dgffggh','C3AD665D2FD8E140'),
('10E47A63B209B240',NULL,'gggggg','C3AD665D2FD8E140'),
('804C4D5BFA66B340',NULL,'kljkluikk','C3AD665D2FD8E140'),
('08D91CBE221FB240','','ghjghkhh','C3AD665D2FD8E140'),
('6017E922491FB240','','hkyuiyujki78oui','C3AD665D2FD8E140'),
('1078D9506F1FB240','','iuopuiuipio[io','C3AD665D2FD8E140'),
('7057D816531FB240','','jhkluiooyuererterteytr','C3AD665D2FD8E140'),
('08C58210A61EB240','','klkklopklhjghgfhgf','C3AD665D2FD8E140'),
('689A1DD90F1FB240','','liopp980','C3AD665D2FD8E140'),
('B01EC81B961FB240','','pkpi','C3AD665D2FD8E140'),
('68C3DEE9DF1EB240','','wereqwqwtwetyrweerw','C3AD665D2FD8E140'),
('60131E0A484BB340','12111111212','Їстивний засіб','C3AD665D2FD8E140'),
('986D6C12568CB140','1234356789','123456789','C3AD665D2FD8E140'),
('D046F5C48E44B040','123456','dffgdfgdghdt','C3AD665D2FD8E140'),
('801E376C2C1FB240','16','16161616','C3AD665D2FD8E140'),
('D0A5B75B1B00AA40','20234234','sdfsdwe','C3AD665D2FD8E140'),
('E076597B4C2DAD40','44444444444444','aaaaaam','C3AD665D2FD8E140'),
('F0B6E4589DDDA940','45446','fgdfdfd','C3AD665D2FD8E140'),
('40F617CF45FBA940','55556788','Тестовый товар 111','C3AD665D2FD8E140'),
('68A29063791FB240','565575','fthtrtrtrtrutr','C3AD665D2FD8E140'),
('A09043BB8FAFB140','64578946556','пгоонгп','C3AD665D2FD8E140'),
('E8BD0547247EB140','6678878yu','ytutiyui7iyu','C3AD665D2FD8E140'),
('58A084409B1FB240','6756','97','C3AD665D2FD8E140'),
('E8EC4943191FB240','6756','uijmnmghhjljklhjkhj','C3AD665D2FD8E140'),
('104F19CF2329B340','hjgfhgfhgfhgfgfu','testtesttest','C3AD665D2FD8E140'),
('187765541D18B240','jk789978','hjkjlljil;hj','C3AD665D2FD8E140')


И наконец "проблемный" скрипт
declare @id char(16), @reccount int
set @id='1078D9506F1FB240'
declare @Str varchar(70)
select @Str = D.CODE from Dictionaries_C3AD665D2FD8E140 as D where (D.recid = @ID)

set @reccount=@@ROWCOUNT
set @Str = IsNull(@Str, '')
select @Str, @reccount

declare cur cursor local scroll for
select top 10 D.CODE, D.recid from Dictionaries_C3AD665D2FD8E140 as D
where ((IsNull(D.CODE, '') < @Str) or ((IsNull(D.CODE, '') = @Str) and (D.recid <= @ID)))
order by D.CODE desc, D.recid desc
open cur
   declare @P1 int
   fetch last from cur into @Str, @ID
     set @P1 = @@CURSOR_ROWS
close cur
deallocate cur
set @Str = IsNull(@Str, '')
select @P1, @Str

select top 20 D.RECTYPE,D.RECID,D.CODE,D.NAME
FROM Dictionaries_C3AD665D2FD8E140 AS D 
where ((IsNull(D.CODE, '') > @Str) or ((IsNull(D.CODE, '') = @Str) and (D.recid >= @ID)))
order by D.CODE asc, D.recid asc


Таблицу можно создать в любой базе, заполнить ее данными, выполнить скрипт и увидеть, что 10 строка в результирующем наборе не будет иметь в колонке RECID значение '1078D9506F1FB240'
13 ноя 13, 14:26    [15121441]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
Glory
Member

Откуда:
Сообщений: 104751
harisma
Таблицу можно создать в любой базе, заполнить ее данными, выполнить скрипт и увидеть, что 10 строка в результирующем наборе не будет иметь в колонке RECID значение '1078D9506F1FB240'

А ничего, что запросы разные
where ((IsNull(D.CODE, '') < @Str) or ((IsNull(D.CODE, '') = @Str) and (D.recid <= @ID))) order by D.CODE desc, D.recid desc
where ((IsNull(D.CODE, '') > @Str) or ((IsNull(D.CODE, '') = @Str) and (D.recid >= @ID))) order by D.CODE asc, D.recid asc
Или вы думаете, что сервер сначала отсортирует записи, а потом начет их фильтровать ?
13 ноя 13, 15:05    [15121901]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
harisma
Member

Откуда:
Сообщений: 243
Glory
А ничего, что запросы разные
where ((IsNull(D.CODE, '') < @Str) or ((IsNull(D.CODE, '') = @Str) and (D.recid <= @ID))) order by D.CODE desc, D.recid desc
where ((IsNull(D.CODE, '') > @Str) or ((IsNull(D.CODE, '') = @Str) and (D.recid >= @ID))) order by D.CODE asc, D.recid asc
Или вы думаете, что сервер сначала отсортирует записи, а потом начет их фильтровать ?

Ну так в том то и вопрос, как этот скрипт правильно переделать, чтобы не зависимо от данных в колонке сортировки, получался правильный результат.
13 ноя 13, 15:14    [15122025]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
daw
Member

Откуда: Муром -> Москва
Сообщений: 7381
harisma,

вы в последнем запросе top 20 уберите и прокрутите все null значения. тут-то разгадку и найдете. все там детерминировано. просто, сравниваете вы isnull(CODE, ''), а сортируете просто по CODE. а null и пустая строка совершенно четко сортируются относительно друг друга, в общем-то.

можете также все isnull-ы убрать - и получите вы свою строку на нужном месте
declare @id char(16), @reccount int
set @id='1078D9506F1FB240'
declare @Str varchar(70)
select @Str = D.CODE from Dictionaries_C3AD665D2FD8E140 as D where (D.recid = @ID)

set @reccount=@@ROWCOUNT
--set @Str = IsNull(@Str, '')
select @Str, @reccount

declare cur cursor local scroll for
select top 10 D.CODE, D.recid from Dictionaries_C3AD665D2FD8E140 as D
where ((D.CODE < @Str or (D.CODE is null and @Str is not null)) or ((D.CODE = @Str or (D.CODE is null and @Str is null)) and (D.recid <= @ID)))
order by D.CODE desc, D.recid desc
open cur
   declare @P1 int
   fetch last from cur into @Str, @ID
     set @P1 = @@CURSOR_ROWS
close cur
deallocate cur
--set @Str = IsNull(@Str, '')
select @P1, @Str

select top 20 D.RECTYPE,D.RECID,D.CODE,D.NAME
FROM Dictionaries_C3AD665D2FD8E140 AS D 
where ((D.CODE > @Str or (D.CODE is not null and @Str is null)) or ((D.CODE = @Str or (D.CODE is null and @Str is null)) and (D.recid >= @ID)))
order by D.CODE asc, D.recid asc
13 ноя 13, 15:23    [15122130]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
daw
Member

Откуда: Муром -> Москва
Сообщений: 7381
из-за этих ваших isnull получилось, что при сравнении в where у вас null=''. а в order by оставалось null < ''.
разумеется, когда в order by добавляли isnull, то и там null становился равным пустой строке и все выправлялось.
13 ноя 13, 15:29    [15122206]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
daw
Member

Откуда: Муром -> Москва
Сообщений: 7381
ну, и в конце добавлю, что, если особо глубокого смысла именно в хранении null-ов нет, то сделайте вы этот ваш CODE уже not null (соответственно поправив вставку/обновление и заменив все уже имеющиеся null на '') и не мучайте ни себя, ни других.
13 ноя 13, 15:35    [15122302]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
harisma
Member

Откуда:
Сообщений: 243
daw
вы в последнем запросе top 20 уберите

Этого делать нельзя по бизнес-логике проекта
daw
из-за этих ваших isnull получилось, что при сравнении в where у вас null=''. а в order by оставалось null < ''.

А можно как-то изменить Order by, чтобы и в нем стало null='', не трогая isnull в условии where? (только говорю сразу что вариант с калькулируемым полем типа IsNull(<сортируемое поле>, <заменитель значения null>) и сортировка уже по этому полю, не подходит, так как из-за этого падает производительность - уже такой вариант проверяли :()
13 ноя 13, 15:39    [15122368]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
harisma
Member

Откуда:
Сообщений: 243
daw
сделайте вы этот ваш CODE уже not null

Это тоже нельзя по бизнес-логике :(
13 ноя 13, 15:41    [15122390]     Ответить | Цитировать Сообщить модератору
 Re: Запрос для получения данных  [new]
daw
Member

Откуда: Муром -> Москва
Сообщений: 7381
> только говорю сразу что вариант с калькулируемым полем типа IsNull(<сортируемое поле>, <заменитель значения null>)
> и сортировка уже по этому полю, не подходит, так как из-за этого падает производительность - уже такой вариант проверяли :(

а проиндексировать его, если?
13 ноя 13, 15:44    [15122434]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить