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

Откуда: Нижний Новгород
Сообщений: 905
прошу подсказать как отредактировать запрос

declare @X integer;
declare @Y integer;
declare @X1 float;
declare @Y1 float;
declare @A integer;
declare @B integer;
declare @C integer;
declare @S float;
declare @D float;
declare @Min float;
declare @T1 table (id int, xtop int, ytop int, xbot int, ybot int)
declare @i integer;
declare @Result integer;
declare @ExistStream bit

insert into @T1
select s.ID, s.XTOP, s.YTOP, s.XBOT, s.YBOT from TSTRUCT s 
where s.KINDOBJ='Связь' and s.idlist=1

declare @k int

set @i=1
set @X=221
set @Y=115
set @Min=1000000

while (@@ROWCOUNT>0)
begin
  select @A=t.ybot-t.ytop from @T1 t 
  select @B=-(t.xbot-t.xtop) from @T1 t
  select @C=t.xbot*t.ytop-t.xtop*t.ybot from @T1 t
  select @S=SQRT(@A*@A+@B*@B)
  
  if ABS((@A*@X+@B*@Y+@C)/@S)<4
  begin
	select @X1=(t.xtop+t.xbot)/2 from @T1 t
	select @Y1=(t.ytop+t.ybot)/2 from @T1 t
	
	select @D=SQRT((@X1-@X)*(@X1-@X)+(@Y1-@Y)*(@Y1-@Y))
	
	if @D<@Min
	begin
		Select @Result=t.id from @T1 t
		set @ExistStream=1
		set @Min=@D
	end
  end 
  select TOP 1 @k=id from sysobjects where @k<id order by id asc 
end;

select @k
select @ExistStream


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

получилось реализовать через курсоры, но в инете пишут что курсоры не рекомендуется использовать.
так же есть информация, что альтернативой курсорам являются таблицы.
как реализовать цикл по таблице?
18 ноя 15, 15:06    [18435994]     Ответить | Цитировать Сообщить модератору
 Re: цикл по временной таблице  [new]
Glory
Member

Откуда:
Сообщений: 104760
nikomp
в результате выдается 2 NULL

А сколько раз срабатывает ваш цикл вы уже узнали ?
18 ноя 15, 15:08    [18436012]     Ответить | Цитировать Сообщить модератору
 Re: цикл по временной таблице  [new]
правильный проходящий.
Guest
nikomp
получилось реализовать через курсоры, но в инете пишут что курсоры не рекомендуется использовать.
так же есть информация, что альтернативой курсорам являются таблицы.
как реализовать цикл по таблице?
Странная логика... Таблицы рекомендуются для ухода от курсоров и неизбежных циклов по ним, а не для хождения по ним циклами. Таблица должна убрать и курсор, и цикл, ЦИКЛ, КАРЛ!
18 ноя 15, 15:10    [18436032]     Ответить | Цитировать Сообщить модератору
 Re: цикл по временной таблице  [new]
nikomp
Member

Откуда: Нижний Новгород
Сообщений: 905
Glory,
ну в консоли выдается сообщение, что обработано строк 7
18 ноя 15, 16:19    [18436545]     Ответить | Цитировать Сообщить модератору
 Re: цикл по временной таблице  [new]
nikomp
Member

Откуда: Нижний Новгород
Сообщений: 905
правильный проходящий.,
а как тогда организовать обработку строк без циклов?
18 ноя 15, 16:20    [18436555]     Ответить | Цитировать Сообщить модератору
 Re: цикл по временной таблице  [new]
правильный проходящий.
Guest
nikomp
Glory,
ну в консоли выдается сообщение, что обработано строк 7
И с чего вы взяли, что это про количество строк, обработанных циклом? Скорее всего это на
insert into @T1
select s.ID, s.XTOP, s.YTOP, s.XBOT, s.YBOT from TSTRUCT s 
where s.KINDOBJ='Связь' and s.idlist=1
18 ноя 15, 16:23    [18436572]     Ответить | Цитировать Сообщить модератору
 Re: цикл по временной таблице  [new]
правильный проходящий.
Guest
nikomp
правильный проходящий.,
а как тогда организовать обработку строк без циклов?
Потрясающе! :) Молча, батенька, молча. Изучив команды работы со множеством строк. В частности Select и Update.
Распишите нам что должен делать ваш цикл с ОДНОЙ записью.
18 ноя 15, 16:26    [18436593]     Ответить | Цитировать Сообщить модератору
 Re: цикл по временной таблице  [new]
nikomp
Member

Откуда: Нижний Новгород
Сообщений: 905
правильный проходящий.,

в таблице перечислены объект, у каждого объекта есть ID и координаты
пользователь кликает мышью в поле клиента, нужно найти объект до которого расстояние будет наименьшим

пробовал организовать цикл немного по другому

  while @i<(select count(*) from @T1)


результат тот-же
18 ноя 15, 17:06    [18436864]     Ответить | Цитировать Сообщить модератору
 Re: цикл по временной таблице  [new]
Glory
Member

Откуда:
Сообщений: 104760
nikomp
результат тот-же

Странно ожидать другого результат. если вы даже не знаете, какие команды вашего скрипта сколько раз выполняются и выполняются ли вообще

Сообщение было отредактировано: 18 ноя 15, 17:10
18 ноя 15, 17:09    [18436887]     Ответить | Цитировать Сообщить модератору
 Re: цикл по временной таблице  [new]
правильный проходящий.
Guest
nikomp
правильный проходящий.,

в таблице перечислены объект, у каждого объекта есть ID и координаты
Прелестно. тестовые данные, полученные вашим запросом
select s.ID, s.XTOP, s.YTOP, s.XBOT, s.YBOT from TSTRUCT s
where s.KINDOBJ='Связь' and s.idlist=1
вы нам покажете? Или предлагаете нам все чисто умозрительно делать?
пользователь кликает мышью в поле клиента, нужно найти объект до которого расстояние будет наименьшим

пробовал организовать цикл немного по другому

  while @i<(select count(*) from @T1)


результат тот-же
Разумеется. Ибо в вашем коде никак не меняется.
Далее:
автор
в результате выдается 2 NULL
А что вы хотели получить от
select @k
select @ExistStream
если запрошенные переменые вычисляются только при
if ABS((@A*@X+@B*@Y+@C)/@S)<4
? Это условие у вас всегда выполняется?
18 ноя 15, 17:18    [18436960]     Ответить | Цитировать Сообщить модератору
 Re: цикл по временной таблице  [new]
как отредактировать запрос
Guest
nikomp
как подозреваю ошибка в том, что в цикле нет четкого позиционирования на строке.
получилось реализовать через курсоры, но в инете пишут что курсоры не рекомендуется использовать.

ну так а с курсором вы же делали позиционирование?
иначе как вообще оно может работать если в каждой итерации запросы выбирают что попало?
если сделали с курсором, то почему тот же самый цикл (с курсором же тот же самый while, какая разница?) сделали уже без where ID = @ID?

курсор/while вообще ничем кроме механизма самого курсора не отличаются - это один и тот же while, одна и та же начитка в каждой итерации значений из новой строчки и абсолютно все то же самое.

количество кода можно легко уменьшить в 2-3 раза если просто в один селект пособирать разбитое зачем-то на 2-3 селекта подряд.
даже больше похоже что одним селектом можно все выбрать и в конце простым where + group by оставить нужное

при чем тут sysobjects и чего вы ждете от неинициализированной @k я честно говоря совсем не понял
подозреваю что это была реализация неправильно понятого нагугленного примера организации цикла без курсора
т.е. должно быть set @id = (select top 1 t.id from <t> t where t.id > @id order by t.id asc)
а перед циклом, соответственно, просто top 1 asc.

курсор заменяют на цикл если к тому есть показания
например, если на вашем не сильно производительном сервере некая функция вызывается в каком-то механизме тысячи раз в небольшую единицу времени, то накладные расходы на организацию курсора внутри этой функции могут себя проявить (за свежие версии не скажу, последний раз такое на 2000 расковыривал)

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

возможно вы не заметили или я что-то упустил, но вроде как вот это все
  select @A=t.ybot-t.ytop from @T1 t 
  select @B=-(t.xbot-t.xtop) from @T1 t
  select @C=t.xbot*t.ytop-t.xtop*t.ybot from @T1 t
  select @S=SQRT(@A*@A+@B*@B)
  
  if ABS((@A*@X+@B*@Y+@C)/@S)<4

от входящих параметров не зависит абсолютно никак, а значит можно или хранить или вычисляемым столбцом сделать.
или засунуть во все тот же "один селект"
18 ноя 15, 18:23    [18437353]     Ответить | Цитировать Сообщить модератору
 Re: цикл по временной таблице  [new]
nikomp
Member

Откуда: Нижний Новгород
Сообщений: 905
как отредактировать запрос,

Спасибо! за ответ.

На всякий случай оставлю тут рабочий код с курсорами. Мне он показался более простым, и как-то понятнее.

declare @X integer;
declare @Y integer;
declare @X1 float;
declare @Y1 float;
declare @A integer;
declare @B integer;
declare @C integer;
declare @S float;
declare @D float;
declare @Min float;
declare @i integer;
declare @Result integer;
declare @ExistStream bit


set @i=1
set @X=221
set @Y=115
set @Min=1000000


declare ct1 cursor read_only
for 
select s.ID, s.XTOP, s.YTOP, s.XBOT, s.YBOT from TSTRUCT s 
where s.KINDOBJ='Связь' and s.idlist=1

declare @id integer
declare @xtop integer;
declare @ytop integer;
declare @xbot integer
declare @ybot integer;

open ct1
fetch next from ct1 into @id, @xtop, @ytop, @xbot, @ybot
while @@FETCH_STATUS=0
begin
  select @A=@ybot-@ytop 
  select @B=-(@xbot-@xtop)
  select @C=@xbot*@ytop-@xtop*@ybot
  select @S=SQRT(@A*@A+@B*@B)
  
  if ABS((@A*@X+@B*@Y+@C)/@S)<4
  begin
	select @X1=(@xtop+@xbot)/2 
	select @Y1=(@ytop+@ybot)/2 
	
	select @D=SQRT((@X1-@X)*(@X1-@X)+(@Y1-@Y)*(@Y1-@Y))
	if @D<@Min
	begin
		Select @Result=@id
		set @ExistStream=1
		set @Min=@D
	end
  end
  fetch next from ct1 into @id, @xtop, @ytop, @xbot, @ybot
end
close ct1
deallocate ct1

Select @Result
20 ноя 15, 08:53    [18445078]     Ответить | Цитировать Сообщить модератору
 Re: цикл по временной таблице  [new]
Serg_77m
Member

Откуда: Донецк
Сообщений: 237
nikomp
На всякий случай оставлю тут рабочий код с курсорами. Мне он показался более простым, и как-то понятнее.
Капец. Такой код лучше оставить в... каком-нибудь C#.
Вот:
declare @X integer;
declare @Y integer;

set @X=221
set @Y=115

select top 1 ID,
  D=SQRT((X1-@X)*(X1-@X)+(Y1-@Y)*(Y1-@Y))
from (
  select a.*,
    X1=(XTOP+XBOT)/2,
    Y1=(YTOP+YBOT)/2 
  from (
    select *,
      S=SQRT(A*A+B*B)
    from (
      select ID,XTOP,XBOT,YTOP,YBOT,
        A=YBOT-YTOP,
        B=-(XBOT-XTOP),
        C=XBOT*YTOP-XTOP*YBOT
      from TSTRUCT s 
      where s.KINDOBJ='Связь' and s.idlist=1
    ) a
  ) a
  where ABS((A*@X+B*@Y+C)/S)<4
) a
order by D

И можно ещё упростить, но здесь сохранены имена промежуточных переменных.
20 ноя 15, 09:22    [18445176]     Ответить | Цитировать Сообщить модератору
 Re: цикл по временной таблице  [new]
Glory
Member

Откуда:
Сообщений: 104760
nikomp
Мне он показался более простым, и как-то понятнее.

По-моему, все это пишется одиним select-ом
20 ноя 15, 09:23    [18445180]     Ответить | Цитировать Сообщить модератору
 Re: цикл по временной таблице  [new]
nikomp
Member

Откуда: Нижний Новгород
Сообщений: 905
Serg_77m,

Согласен, ваш код, значительно лучше, спасибо! подскажите только какая роль отводится "a" это псевдоним для результатов вложенных запросов?
20 ноя 15, 10:11    [18445397]     Ответить | Цитировать Сообщить модератору
 Re: цикл по временной таблице  [new]
Serg_77m
Member

Откуда: Донецк
Сообщений: 237
nikomp
Serg_77m,

Согласен, ваш код, значительно лучше, спасибо! подскажите только какая роль отводится "a" это псевдоним для результатов вложенных запросов?
Да. Вложенные запросы должны иметь псевдоним.
20 ноя 15, 10:15    [18445420]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить