Выберите строки, в которых значение изменяется - PullRequest
1 голос
/ 20 декабря 2010

У меня есть таблица в базе данных доступа со столбцами для описания работы, проекта, даты и необходимой суммы. Для каждого описания я хочу выбрать первую запись даты для каждого комбинированного задания / проекта, а также строки, в которых изменяется сумма.

Итак, если у меня есть

Job        proj date     amt
Programmer 105  01-01-11 3
Programmer 105  01-02-11 3
Programmer 105  01-03-11 2
Programmer 105  01-04-11 2
Programmer 105  01-05-11 3
Programmer 110  01-03-11 1
Programmer 110  01-04-11 2
Programmer 110  01-05-11 3
Manager    105  01-01-11 1
Manager    105  01-02-11 2
Manager    105  01-03-11 2
Manager    105  01-04-11 2
Manager    105  01-05-11 2

Я хочу выбрать

Programmer 105  01-01-11 3
Programmer 105  01-03-11 2
Programmer 105  01-05-11 3
Programmer 110  01-03-11 1
Programmer 110  01-04-11 2
Programmer 110  01-05-11 3
Manager    105  01-01-11 1
Manager    105  01-02-11 2

У меня есть таблица с различными описаниями заданий, которые можно использовать.

Ответы [ 2 ]

2 голосов
/ 20 декабря 2010

Первая запись всегда будет иметь значение Null для nextamt:

SELECT j.Job,
    j.proj,
    j.Date,
    j.amt,
    (SELECT TOP 1 amt 
     FROM jobs q 
     WHERE q.job=j.job AND q.proj=j.proj AND q.date<j.date 
     ORDER BY [date] DESC) AS nextamt 
FROM jobs AS j 
WHERE ((SELECT TOP 1 amt 
        FROM jobs q 
        WHERE q.job=j.job AND q.proj=j.proj AND q.date<j.date 
        ORDER BY [date] DESC)) <>[amt] 
Or ((SELECT TOP 1 amt 
     FROM jobs q 
     WHERE q.job=j.job AND q.proj=j.proj AND q.date<j.date 
     ORDER BY [date] DESC)) Is Null
2 голосов
/ 20 декабря 2010

Это можно легко сделать с помощью аналитических (оконных) функций, доступных в Oracle / SQL-Server / etc (Google для lag, lead, first_value, last_value и т. Д. И т. Д.), Но Access не поддерживает их, поэтому вам придется присоединиться к чему-то вроде этого:

SELECT 
    rows.Job, rows.proj, rows.dte, curr.amt 
FROM
    ((SELECT Data.Job, Data.proj, Data.dte, 
        (SELECT max(dte) 
         FROM data as prev 
         WHERE prev.job = data.job and 
               prev.proj = data.proj and 
               prev.dte < data.dte) AS prev_dte 
     FROM Data) as [rows] 
     INNER JOIN Data AS curr 
               ON (rows.dte = curr.dte) AND 
                  (rows.proj = curr.proj) AND 
                  (rows.Job = curr.Job)
)
    LEFT JOIN Data AS prev 
         ON (rows.prev_dte = prev.dte) AND 
            (rows.proj = prev.proj) AND 
            (rows.Job = prev.Job) 
WHERE 
    prev.amt<>[curr].[amt] OR 
    prev.Job Is Null;

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

(Возникли проблемы с форматированием кода - извините.)

Редактировать: вот вывод, который, я думаю, вам нужен.

Job         proj    dte             amt
Programmer  105     01/01/2011  3 
Programmer  105     03/01/2011  2 
Programmer  105     05/01/2011  3 
Programmer  110     03/01/2011  1 
Programmer  110     04/01/2011  2 
Programmer  110     05/01/2011  3 
Manager     105     01/01/2011  1 
Manager     105     02/01/2011  2 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...