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

Запросы, планы, оптимизация запросов, ...

Модераторы: kdv, CyberMax

Ответить
shrk
Сообщения: 2
Зарегистрирован: 12 окт 2005, 15:02

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

Сообщение shrk » 12 окт 2005, 15:36

Можно ли 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 ?

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 12 окт 2005, 15:42

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

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 12 окт 2005, 15:45

результат sql-запроса это множество, поэтому там нет "предыдуших", "следующих", "первых", "последних" и т.п.

shrk
Сообщения: 2
Зарегистрирован: 12 окт 2005, 15:02

Сообщение shrk » 12 окт 2005, 15:49

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

Pop
Сообщения: 2
Зарегистрирован: 03 окт 2005, 10:39

Сообщение Pop » 13 окт 2005, 07:22

Странноватая задача. Если не секрет, зачем это надо?

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

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

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)

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 13 окт 2005, 09:39

ХП с одним циклом 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

m00m
Сообщения: 2
Зарегистрирован: 05 окт 2005, 12:37

Сообщение m00m » 13 окт 2005, 18:30

to Ivan_Pisarevsky:

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

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 14 окт 2005, 08:17

Неправда Ваша, дяденька Биденко (с)

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

m00m
Сообщения: 2
Зарегистрирован: 05 окт 2005, 12:37

Сообщение m00m » 14 окт 2005, 16:56

таки да, действительно вернет...
не поленился проверить :)

Ответить