Страница 1 из 1

Как сделать запрос

Добавлено: 17 ноя 2004, 09:43
RhinoFC
Есть запрос вида:

Код: Выделить всё

select fld1, fld2 from table1
where [некое условие]
order by fld2 desc
rows 1
Запрос вернет одну запись, где fld2 - максимальное (из диапазона записей, удовлетворяющих условию выборки).

Мне нужно сделать тоже самое, но не используя rows.
Все это дело будет использовано внутри ХП, и первое, что приходит на ум, это найти сначала, максимальное значение fld2 из записей, удовлетворяющих условию выборки. Но это тяжко. Процедура будет работать очень медленно. Как вообще решались такие проблемы до появления Rows?

Добавлено: 17 ноя 2004, 10:40
kdv
в процедурах - никак. на клиенте - выбиралась первая запись и потом запрос закрывался, т.е. выборка всех остальных записей не делалась. rows/first делает именно это, в т.ч. в процедурах.

Добавлено: 17 ноя 2004, 10:50
sag
> Мне нужно сделать тоже самое, но не
> используя rows. Все это дело будет
> использовано внутри ХП

в хп делай цикл FOR SELECT по этому запросу, а после
получения первой записи выходи из цикла

Добавлено: 17 ноя 2004, 11:07
Гость
sag писал(а):в хп делай цикл FOR SELECT по этому запросу, а после
получения первой записи выходи из цикла
Интересно. И как же в хп выйти из цикла? Я понимаю, конечно, что можно в цикле просмотреть одну запись а остальные проигнорировать. Но цикл-то все равно прокрутит все записи. Может быть и черт с ним, если это не займет много времени. Как думаете?

Добавлено: 17 ноя 2004, 11:32
RhinoFC
Может быть в этом случае вообще сделать вот так?:

Код: Выделить всё

for select fld1, fld2 from table1
where [некое условие]
order by fld2 /* ASC */
into :f1, :f2
do
begin
  f1 = f1;
end
Тогда ведь в f1 и f2 окажутся как раз значения из нужной записи. Но, во-первых, цикл все-равно пройдет по всем записям, а во-вторых необходим какой-нибудь "пустой" оператор, который ничего не делает (я выбрал f1=f2), кроме того, что тратит процессорное время.

Добавлено: 17 ноя 2004, 11:35
sag
> И как же в хп выйти из цикла? Я понимаю, конечно,
> что можно в цикле просмотреть одну запись а
> остальные проигнорировать.

Не, это не наши методы.
На «старых» иб-подобных для этих целей можно применить,
например, механизм пользовательских исключений:

...
/*получаем первую запись запроса*/
begin
for select ...
do
begin
...
exception my_exception; /*"возбуждаем" исключение*/
end
when exception my_exception do ...; /*ловим исключение
после первой итерации цикла*/
end
.... /*продолжаем выполнение хп*/

Добавлено: 17 ноя 2004, 11:36
dimitr
Из FOR SELECT цикла можно выйти, выбросив исключение и перехватив его потом на уровень выше в пустом WHEN-обработчике. Я так понимаю, что сервер - IB?

Добавлено: 17 ноя 2004, 12:14
RhinoFC
sag, спасибо. Помогло :)

Добавлено: 17 ноя 2004, 13:34
Гость
А так не проще (для 1 строки):

Код: Выделить всё

Select fld1, fld2 from table1 
where [некое условие] 
order by fld2 /* ASC */ 
into :f1, :f2 ;
suspend;
Для X строк - While и переменная-счетчик.

Добавлено: 17 ноя 2004, 15:03
sag
> А так не проще (для 1 строки):
> Select fld1, fld2 from table1
> where [некое условие]

Что есть "некое условие"? Каждому пользователю системы раздать по генератору? Если ты имеешь в виду что-то другое, то научи, пжалста.

Добавлено: 18 ноя 2004, 16:24
Vemer
Имелось ввиду что просто
Select ... Into ..; Suspend;(без For)
Вернет первую строку в выходные параметры независимо от условий.
А кол-во нужных строк можно задавать с помощью входного параметра. И при чем тут генераторы?

Добавлено: 19 ноя 2004, 08:23
sag
> Имелось ввиду что просто
> Select ... Into ..; Suspend;(без For)
> Вернет первую строку в выходные параметры
> независимо от условий. А кол-во нужных строк
> можно задавать с помощью входного параметра.

?
В случае если этот запрос возвращает только одну строку, то он ее единственную и, в этом случае, первую (последнюю) же и вернет. Если же запрос возвращает несколько строк, то получите пожалуйста: "multiple rows in singleton select". Это требовалось? И как здесь можно задействовать входной параметр?

>И при чем тут генераторы?

Если не брать вариант с перебором всех строк выборки (посредством for select-а), есть еще извратный вариант пригодный для однопользовательских систем или для очень-очень редких операций. Я имею в виду использование проверки значения генератора в секции where запроса.
...
i=gen_id(my_generator, ...); /*устанавливаем генератор в единицу, например*/
for
select ...
from ...
where gen_id(my_generator,0)>0 /*проверяем значение генератора, это и есть некое условие*/
order by ...
into :...
do
begin
suspend;
i=gen_id(my_generator, ...); /*устанавливаем генератор в ноль*/
end
/*получили первую запись и продолжаем выполнение хп*/