Как получить значение из предыдущей строки результата оператора SELECT? - PullRequest
4 голосов
/ 12 апреля 2009

Если у нас есть таблица FollowUp, в которой есть строки [ID (int), Value (Money)] и у нас есть несколько строк, например
ID - значение
1 ------ 70
2 ------ 100
3 ------ 150
8 ------ 200
20 ----- 250
45 ----- 280
и мы хотим создать один SQL-запрос, который получит каждый идентификатор строки, значение и предыдущее значение строки, в котором данные отображаются следующим образом
ID --- значение --- Prev_Value
1 ----- 70 ---------- 0
2 ----- 100 -------- 70
3 ----- 150 -------- 100
8 ----- 200 -------- 150
20 ---- 250 -------- 200
45 ---- 280 -------- 250

я делаю следующий запрос, но мне кажется, что производительность огромного количества данных настолько плоха

SELECT FollowUp.ID, FollowUp.Value,
(   
      SELECT F1.Value
      FROM FollowUp as F1 where 
      F1.ID =
             ( 
                SELECT  Max(F2.ID) 
                FROM FollowUp as F2 where F2.ID < FollowUp.ID  
             ) 
) AS Prev_Value
FROM FollowUp

Так может ли кто-нибудь помочь мне найти лучшее решение для такой проблемы?

Ответы [ 6 ]

4 голосов
/ 14 апреля 2009

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

SELECT followup.value, 
    ( SELECT TOP 1 f1.VALUE 
      FROM followup as f1 
      WHERE f1.id<followup.id 
      ORDER BY f1.id DESC
    ) AS Prev_Value
FROM followup

НТН

3 голосов
/ 12 апреля 2009

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

select
    rownr = row_number() over (order by id)
,   value
from your_table

С помощью цифр вы можете легко найти предыдущий ряд:

with numbered_rows
as (
    select
        rownr = row_number() over (order by id)
    ,   value
    from your_table
)
select
    cur.value
,   IsNull(prev.value,0)
from numbered_rows cur
left join numbered_rows prev on cur.rownr = prev.rownr + 1

Надеюсь, это полезно.

2 голосов
/ 14 апреля 2009

Это не ответ на ваш актуальный вопрос.

Вместо этого я чувствую, что вы подходите к проблеме с неправильной стороны: В правильно нормализованных реляционных базах данных кортежи («строки») каждой таблицы должны содержать ссылки на другие элементы БД вместо фактических значений. Поддержание этих отношений между кортежами относится к части вставки данных кодовой базы. То есть, если значение кортежа с ближайшим меньшим номером идентификатора действительно принадлежит вашей модели данных.

Если требование знать предыдущее значение исходит из части представления приложения, то есть из единого представления данных, которое должно быть определенным образом отформатировано, следует извлечь содержимое, отсортированное по id, и обрабатывать требование с учетом конкретного кода.

В вашем случае я бы предположил, что знание значения предыдущих кортежей действительно будет принадлежать к коду представления, а не к базе данных.

РЕДАКТИРОВАТЬ: Вы упомянули, что вы храните их отдельно и просто хотите сделать запрос для этого. Тем не менее, код приложения, вероятно, был бы более логичным местом для такого объединения.

0 голосов
/ 31 октября 2015

Вы можете использовать функцию 'LAG'.

     SELECT ID,
            Value,
            LAG(value) OVER(ORDER BY ID) AS Prev_Value
     FROM FOLLOWUP;
0 голосов
/ 12 апреля 2009

Создайте хранимую процедуру и используйте курсор для итерации и создания строк.

0 голосов
/ 12 апреля 2009

Как насчет того, чтобы вставить строки в ваше приложение и вычислить там предыдущее значение?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...