有关数据库设计/ SQL的建议,用于按时间顺序检索数据

时间:2010-03-14 17:51:12

标签: sql sql-server database-design

我正在创建一个数据库,以帮助跟踪哪些员工参加过某个培训课程。我想就设计数据库的最佳方法获得一些指导。

具体而言,每位员工每年必须参加培训课程,我的数据库需要保留他们过去参加课程的所有日期的历史记录。

最终用户将使用该软件作为计划工具,帮助他们预订员工未来的课程日期。当他们选择给定的员工时,他们会看到:

  • (a)上次出勤日期
  • (b)预计未来出勤日期(即上次出勤日期+ 1个日历年)

就我的数据库而言,任何特定员工可能有多个过去的课程出勤日期:

EmpName          AttandanceDate

Joe Bloggs             1st Jan 2007
Joe Bloggs           4th Jan 2008
Joe Bloggs           3rd Jan 2009
Joe Bloggs           8th Jan 2010

我的问题是,设置数据库的最佳方法是什么,以便轻松检索最近的课程出勤日期?在上面的示例中,最新的将是2010年1月8日。

有没有一种好方法可以使用SQL按日期排序并选择MAX日期?

我的另一个想法是添加一个名为“MostRecent”的列,并将其设置为TRUE。

EmpName    AttandanceDate         MostRecent
Joe Bloggs  1st Jan 2007           False
Joe Bloggs  4th Jan 2008           False
Joe Bloggs  3rd Jan 2009           False
Joe Bloggs  8th Jan 2010           True

我想知道这是否会简化SQL,即

SELECT Joe Bloggs WHERE MostRecent = ‘TRUE’

此外,当用户更新给定员工的出勤记录(即最新出勤日期)时,我可以使用SQL来:

  1. 搜索员工并设置 MostRecent值为FALSE
  2. 添加MostRecent设置为TRUE的新记录?
  3. 有人会推荐两种方法吗?或者你有一个完全不同的方法来解决这个问题?

4 个答案:

答案 0 :(得分:3)

要获得上次出勤日期,请使用名为MAX的组功能,即

SELECT MAX(AttandanceDate)  
FROM   course_data
WHERE  employee_name = 'Joe Bloggs'

获取所有员工的最长出勤日期:

SELECT   employee_name, MAX(AttandanceDate)  
FROM     course_data
GROUP BY employee_name
ORDER BY employee_name

上面的查询将 NOT 返回未参加任何课程的员工的数据。所以你需要执行不同的查询。

SELECT   A.employee_name, B.AttandanceDate
FROM     employee AS A
LEFT JOIN (
           SELECT   employee_id, MAX(AttandanceDate) AS AttandanceDate
           FROM     course_data
           GROUP BY employee_id
          ) AS B ON A.id = B.employee_id
ORDER BY A.employee_name

对于没有参加任何课程的员工,查询将返回NULL AttendanceDate

答案 1 :(得分:0)

标志是多余的。另一种方式是如何让员工上次参加上课:

select top 1 AttandanceDate
from course_data
WHERE  employee_name = 'Joe Bloggs'
order by AttandanceDate desc

答案 2 :(得分:0)

可能已经是这种情况了,但是AttandanceDate列的输出让我怀疑该列可能不是日期时间列。大多数RDBMS都有某种日期,时间和/或日期时间数据类型用于存储此信息。其中KandadaBoggu的AND OMG小马的反应是完美的。但是,如果您将日期存储为字符串,则会在尝试执行任何建议时遇到问题。

使用日期时间数据类型通常也会让您了解获取日期详细信息的可能性,如:

e.g。 SELECT YEAR(2008-01-01)将以整数形式返回2008。

答案 3 :(得分:0)

如果您运行的是SQL Server 2005或2008或更高版本,则可以使用row_number()执行以下操作。这将列出每个人最近的出席情况。

with temp1 as 
 (select *
      , (row_number() over (partition by EmpName order by AttandanceDate descending)) 
        as [CourseAttendanceOrder]
    from AttendanceHistory)
select *
  from temp
 where CourseAttendanceOrder = 1
 order by EmpName

这可以放在视图中,以便您可以根据需要使用它。

但是,如果您始终只关注一个人,那么创建一个可以使用select max(AttandanceDate)之类的语句的存储过程对于您正在处理的人来说可能更有效。