SQL выберите значение, если в другой таблице нет соответствующего значения - PullRequest
2 голосов
/ 01 апреля 2009

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

Таблица: сотрудник

Id  | Name      | Department
-----------------------------
0   | Alice     | 1
1   | Bob       | 1

Таблица: История

ChangeDate   | Field      | RowId  | NewValue    
---------------------------------------------
05/05/2009   | Department | 0      | 2

В нем указывается, что сотрудник 0 (Алиса) переместится в отдел 2 05.05.2009.

Я хочу написать запрос, чтобы определить отдел сотрудника на определенную дату. Так что нужно:

  • Найти первую запись истории для этого поля и сотрудника до указанной даты
  • Если ничего не существует, по умолчанию используется текущее значение в основной таблице сотрудников.

Как я могу это сделать? Моя интуиция состоит в том, чтобы выбрать первую строку набора результатов, в которой все подходящие записи истории упорядочены в обратном порядке по дате и последним значением в основной таблице (так что это только первый результат, если нет подходящих записей истории), но я не для этого не требуется SQL-фу.


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

Ответы [ 2 ]

2 голосов
/ 01 апреля 2009
SELECT  COALESCE (
        (
        SELECT  newValue
        FROM    history
        WHERE   field = 'Department'
                AND rowID = ID
                AND changeDate =
                (
                SELECT MAX(changedate)
                FROM   history
                WHERE  field = 'Department'
                       AND rowID = ID
                       AND changeDate <= '01/01/2009'
                )
        ), department)
FROM    employee
WHERE   id = @id

В Oracle и MS SQL вы также можете использовать это:

SELECT  COALESCE(newValue, department)
FROM    (
        SELECT  e.*, h.*,
                ROW_NUMBER() OVER (PARTITION BY e.id ORDER BY changeDate) AS rn
        FROM    employee e
        LEFT OUTER JOIN
                history h
        ON      field = 'Department'
                AND rowID = ID
                AND changeDate <= '01/01/2009'
        WHERE   e.id = @id
        )
WHERE rn = 1

Обратите внимание, что ROWID является зарезервированным словом в Oracle, поэтому вам потребуется переименовать этот столбец при переносе.

1 голос
/ 01 апреля 2009

Это должно работать:

select iif(history.newvalue is null, employee.department, history.newvalue)
as Department
from employee left outer join history on history.RowId = employee.Id
and history.changedate < '2008-05-20'  // (i.e. given date)
and history.changedate = (select max(changedate) from history h1
where h1.RowId = history.RowId and h1.changedate <= history.changedate)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...