Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > СУБД, общие вопросы > Достать предыдущие значения


Автор: Platon 4.12.2008, 21:12
Здравствуйте, уважаемые.

Трудно сформулировать, чего я хочу. 

есть данные

Цитата

eId  kId   position  scan_time   id
 1     1        1             1           1
 1     2        3             1           2
 2     1        5             1           3
 2     2        5             1           4

 1     1        5             2           5
 1     2        6             2           6
 2     1        7             2           7
 2     2        8             2           8

 1     1        4             3           9
 1     2        5             3           10
 2     1        6             3           11
 2     2        9             3           12


Мне нужно составить список eId, kId, position, id для "предыдущего сеанса (scan_time)" по отношению к заданному для каждого ключа(если так можно выразиться) "eId kId" . Но предыдущего не совсем.
Пример по данным: по отношению к scan_time = 3 список будет следующий
Цитата

eId  kId   position  scan_time   id
 1     1        5             2           5
 1     2        6             2           6
 2     1        7             2           7
 2     2        8             2           8


Если же в таблице данных будет отсутствовать запись с ID = 7, то получится:
Цитата

eId  kId   position  scan_time   id
 1     1        5             2           5
 1     2        6             2           6
 2     1        5             1           3
 2     2        8             2           8


Эквивалентный запрос:
Код

SELECT eId, kId, position FROM ttt AS t1 
WHERE scan_time = (SELECT MAX(scan_time) 
                              FROM ttt AS t2 
                              WHERE t2.scan_time < ? AND t2.eId = t1.eId AND t2.kId = t1.kId
                           )

Но такой запрос только на утилизацию, что я и делаю smile

Прошу о помощи.

Автор: Akella 5.12.2008, 09:38
Код

SELECT eId, kId, position FROM ttt AS t1 
WHERE scan_time = :param1 - 1

задаёшь в параметре значение и тебе будет результат с учётом - 1
или я чего-то недопонял?

Автор: Zloxa 5.12.2008, 09:58
Целевая платформа?
Почему Ваш запрос "на утилизацию"?

Автор: Platon 5.12.2008, 10:32
Zloxa, H2DB


Akella, существуют точки разрыва. Как привел пример 
Цитата(Platon @  4.12.2008,  22:12 Найти цитируемый пост)
Если же в таблице данных будет отсутствовать запись с ID = 7, то получится:


Цитата

eId  kId   position  scan_time   id
 1     1        5             2           5
 1     2        6             2           6
 2     1        5             1           3
 2     2        8             2           8


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

Для каждого eId, kId выполнять такой запрос 
Код

SELECT position FROM ttt 
WHERE eId = :eId AND kId = :kId AND scan_time = 
             (SELECT MAX(scan_time) FROM ttt
              WHERE eId = :eId AND kId = :kId AND scan_time < :reqScanTime
             )

Автор: Zloxa 5.12.2008, 10:42
Код

select eId,kid
       ,to_number(substr(max(lpad(scan_time,40,'0')||position),41)) last_position
       ,max(scan_time) last_scan
  from ttt
  where scan_time < 3
group by eId,kid;
 
       EID        KID LAST_POSITION  LAST_SCAN
---------- ---------- ------------- ----------
         1          1             5          2
         1          2             6          2
         2          1             5          1
         2          2             8          2
 
SQL> 

Этот подход в ораклином форуме на sql.ru называют "бабушкиным методом".
Этот метод использовался до появления ранжирующих функций в диалекте оракла.
Cуть метода - составить строку, которая начинается с ранжируемого значения а в хвосте несет информационную стоставлющую, вычислить аггрегат по полученной строке, затем разобрать ее и извлечь информационную стоставлющую.
В нашем примере мы ранжируемся по scan_time. В аггрегируемом выражении мы переводим значение scan_time в строку и дополняем лидирующими нулями до максимальной разрядности числа (в оракле это 40. если у нас scan_time int(10), достаточно будет дополнять до 10 символов) для того, чтобы упорядочивание по строковому представлению совпадало с упорядочиванием по числовому представлению. Хвостиком, мы цепляем к строке position. После вычисления максимального значения из полученной строки извлекаем position.

Данный подход не совсем красив и эстетичен. Но позволяет одним проходом, без джойнов достичь желаемого. И, он весьма универсален. Достаточно лишь перевести строковые функции на диалект целевой платформы.

Автор: Platon 5.12.2008, 13:30
Zloxa, оох какая интересная теория! Спасибо попробую.

Автор: Platon 5.12.2008, 15:48
Оформил. Работает. 
Zloxa, +1!!!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)