2009-07-01 3 views
3

Как получить значение из предыдущей строки результата инструкции SELECTКАК ВЫБРАТЬ ПРЕДЫДУЩАЯ ЗНАЧИТЕЛЬНАЯ ЗНАЧКА?

Если у нас есть таблица под названием cardevent и имеет строки [ID (int), Value (Money)], и у нас есть несколько строк в ней, например

ID --Value 

1------70 
1------90 
2------100 
2------150 
2------300 
3------150 
3------200 
3-----250 
3-----280 

так далее ...

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

ID --- Value ---Prev_Value 

1 ----- 70 ---------- 0 
1 ----- 90 ---------- 70 
2 ----- 100 -------- 90 
2 ------150 -------- 100 
2 ------300 -------- 150 
3 ----- 150 -------- 300 
3 ----- 200 -------- 150 
3 ---- 250 -------- 200 
3 ---- 280 -------- 250 

и далее.

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

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

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

+2

почему вы помечены 2 различных РСУБД? –

+0

Дубликат этого (другой пользователь, другое имя таблицы): http://stackoverflow.com/questions/742226/how-to-get-a-value-from-previous-result-row-of-a-select- заявление – MicSim

+1

должно быть домашним вопросом .... –

ответ

5

Это один должен работать нормально для обеих баз данных:

SELECT cardevent.ID, cardevent.Value, 
    (SELECT TOP 1 F1.Value 
    FROM cardevent as F1 
    WHERE F1.ID < cardevent.ID 
    ORDER BY F1.ID DESC 
    ) AS Prev_Value 
FROM cardevent 

Update: Предполагая, что идентификатор не является уникальным, но сочетание ID и Значение уникально (вы должны указать, что накладывает ваш заказ на стол, так что вы знаете, что такое предыдущая строка), вы должны использовать этот запрос:

select cardevent.ID, cardevent.Value, 
    (select TOP 1 F1.Value from cardevent as F1 
    where (F1.ID < cardevent.ID) or (F1.ID = cardevent.ID and F1.Value < cardevent.Value) 
    order by F1.ID DESC, F1.Value DESC 
    ) AS Prev_Value 
from cardevent 
+0

@MicSim - Я использовал свой запрос, но Показаны ошибки «В большинстве одна запись может быть возвращена подзапросом» ничего не экспонируется в prev_value поле – Gopal

+0

Output Показывается, как это .... PersonId \t \t CARDEVENTDATE Expr1002 \t Prev_Value #name ? \t # Имя? \t # Имя?\t # Имя? # Имя? \t # Имя? \t # Имя? \t # Имя? # Имя? \t # Имя? \t # Имя? \t # Имя? # Имя? \t # Имя? \t # Имя? \t # Имя? – Gopal

+0

Просто протестированный выше запрос с Access 2000 (здесь нет 2003), и он работает. Возможно, вы добавили/изменили запрос? – MicSim

2

попробовать что-то вроде этого:

SELECT C.ID, C.Value, COALESCE(C1.Value, 0) 
FROM cardevent C 
    LEFT JOIN cardevent C1 
    ON C1.Id = (SELECT MAX(id) FROM cardevent C2 where C2.Id < C.Id) 
+0

+1. Это, по-видимому, является постом всех данных решений. –

+0

Кажется, что он скомпилирован с тем же планом выполнения, что и решение MicSim, и имеет смысл, если вы посмотрите внимательно. Я бы сказал, что все в порядке. –

+0

Я не выглядел достаточно близко к фактическим планам выполнения, только в процентах, заданных SQL Server. Все решения работают afaik, основное отличие - время выполнения и читаемость. Ваш самый быстрый (или такой же быстрый, как решение MicSim), и самый читаемый. Шахта ... ну, не очень хорошая

0

Как выполняет следующие действия?

SELECT F1.ID, F1.Value, F3.Value 
FROM cardevent F1 
    INNER JOIN (
     SELECT F1.ID, mID = MAX(F2.ID) 
     FROM cardevent F1 
      INNER JOIN cardevent F2 ON F2.ID < F1.ID 
     GROUP BY F1.ID 
    ) F2 ON F2.id = F1.ID 
    INNER JOIN cardevent F3 ON F3.ID = F2.mID 
UNION ALL 
SELECT F1.ID, F1.Value, 0 
FROM cardevent F1 
    INNER JOIN (
     SELECT ID = MIN(ID) 
     FROM cardevent 
    ) F2 ON F2.ID = F1.ID 
ORDER BY 1 
0

Я предпочитаю TOP 1 вместо MAX(...), что ИМХО должно быть также быстрее:

SELECT  C.ID, C.Value, COALESCE(C1.Value, 0) 
FROM  cardevent C 
LEFT JOIN cardevent C1 
     ON C1.ID = (SELECT TOP 1 C2.ID FROM cardevent C2 WHERE C2.ID < C.ID ORDER BY C2.ID) 
+0

Используя базу данных доступа 2003, не принимает функцию коалесценции – Gopal

+0

@Gopal: Я не говорю об эффективности кода в MSAccess, но IIF и ISNULL должны помочь: «IIF (ISNULL (C1.Value), 0, C1.Value)) " – van

Смежные вопросы