我有一个数据库,它尝试通过一个主表和一个历史表来获取时间点信息,该历史表记录另一个表中的字段何时将/确实发生更改。例如
表:员工
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。
注意:我意识到这可能不是实现该系统的最佳方式 - 我无法在短期内改变这一点 - 但如果您能提出更好的方法来实现此系统,我会很高兴听到这个消息。
最佳答案
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
中的保留字,因此在移植时需要重命名此列。
关于如果另一个表中不存在对应的值,则 SQL 选择值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/706236/