我有一个数据库,它试图通过一个主表和一个历史表来记录时间点信息,该表记录了另一个表中的字段何时会发生变化。 e.g。
表:员工
Id | Name | Department
-----------------------------
0 | Alice | 1
1 | Bob | 1
表:历史记录
ChangeDate | Field | RowId | NewValue
---------------------------------------------
05/05/2009 | Department | 0 | 2
记录员工0(Alice)将于05/05/2009移至部门2。
我想写一个查询来确定特定日期的员工部门。所以它需要:
我该怎么做?我的直觉是选择结果集的第一行,该结果集具有按日期反向排序的所有合适的历史记录以及最后一个主表中的值(所以如果没有合适的历史记录,它只是第一个结果),但我不知道没有必要的SQL-fu来实现这一点。
注意:我意识到这可能不是实现这个系统的最佳方式 - 我无法在短期内改变这一点 - 尽管如果你能建议一个更好的方法来实现这个我很高兴听到它。
答案 0 :(得分:2)
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 :(得分:1)
这应该有效:
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)