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

Выбор в одну строку двух соседних записей из таблицы

Добавлено: 12 окт 2005, 15:36
shrk
Можно ли SQL-запросом сделать следуещее:
к каждой строчке таблицы приписать "предыдущую", и посчитать там разницу некоторых полей, т.е. то, что изменилось по сравнению с "предыдыущей"
понятие "предыдущей" можно определить как "ближайшая по некоторому критерию но не равная ей",
например предыдущая по дате, по массе, по росту.
т.е. из таблицы вида
01.01.2001 "строка 1"
02.01.2001 "строка 2"
05.01.2001 "строка 3"

получить

01.01.2001 "строка 1" NULL NULL
02.01.2001 "строка 2" 01.01.2001 "строка 1"
05.01.2001 "строка 3" 02.01.2001 "строка 2"

в данном случае выбирается предыдущая по дате.
или например, есть таблица с данными на людей (рост, вес, размер одежды и т.д.)
их можно сгруппировать, например, по росту (GROUP BY "рост") получив данные со средними данными по весу, и размеру одежды людей разного роста. Как теперь запросом получить из этих данных, на сколько отличается вес у людей разного роста?
что-то вроде
Рост Вес Отличие_от_предыдущей_группы_рост Отличие_от_предыдущей_группы_вес
150 48 NULL NULL
160 63 10 15
180 75 20 12

В Oracle можно использовать для этой цели rownum и вложенный select . Можно ли это сделать в Firebird 1.5 ?

Добавлено: 12 окт 2005, 15:42
Dimitry Sibiryakov
Проще всего это сделать на клиенте или в Хранимой Процедуре по мере перебора записей, отсортированных по соответствующему критерию.

Добавлено: 12 окт 2005, 15:45
kdv
результат sql-запроса это множество, поэтому там нет "предыдуших", "следующих", "первых", "последних" и т.п.

Добавлено: 12 окт 2005, 15:49
shrk
kdv писал(а):результат sql-запроса это множество, поэтому там нет "предыдуших", "следующих", "первых", "последних" и т.п.
хорошо, не "предыдущей", а "ближайшей по некоторому критерию, но не являющейся ей самой"

Добавлено: 13 окт 2005, 07:22
Pop
Странноватая задача. Если не секрет, зачем это надо?

Можно попробовать вот так:

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

select moment, stroka,
(select first 1 moment from new_table in_table where in_table.moment<out_table.moment
order by moment desc),
(select first 1 stroka from new_table in_table where in_table.moment<out_table.moment
order by moment desc)
from new_table out_table order by moment asc
Или лучше вот так:

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

select out_table.*,
in_table.*
from new_table out_table
left join new_table in_table
 on in_table.moment=(select max(moment) from new_table tmp where tmp.moment<out_table.moment)

Добавлено: 13 окт 2005, 09:39
Ivan_Pisarevsky
ХП с одним циклом for select и все собственно. Если проблема написать такю ерунду, ну вот готовая:

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

create procedure some_proc returns(last_rost integer, last_ves integer, prev_rost integer, prev_ves)
as
begin
  prev_rost = NULL;
  prev_ves = NULL;
  for 
    select 
      rost, 
      ves
    from some_table
    order by rost, ves
    into :last_rost, :last_ves
  do
  begin
     suspend;
     prev_rost = last_rost;
     prev_ves = last_ves;
  end 
end

Добавлено: 13 окт 2005, 18:30
m00m
to Ivan_Pisarevsky:

Все хорошо, только последнюю найденную строку эта XP "зевнет".

Добавлено: 14 окт 2005, 08:17
Ivan_Pisarevsky
Неправда Ваша, дяденька Биденко (с)

Хп вернет данные строго, как в первом посте вопрошает автор топика :wink:

Добавлено: 14 окт 2005, 16:56
m00m
таки да, действительно вернет...
не поленился проверить :)