【问题标题】:Advice on database design / SQL for retrieving data with chronological order有关按时间顺序检索数据的数据库设计/SQL 的建议
【发布时间】:2010-03-14 17:51:11
【问题描述】:

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

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

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

  • (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 的新记录?

有人会推荐其中一种方法吗?或者你有完全不同的方法来解决这个问题?

【问题讨论】:

    标签: sql sql-server database-design


    【解决方案1】:

    要获取最后的出勤日期,请使用名为 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
    

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

    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:对于 OP - 由于日期值,标志值是多余的。日期值表示一个人参加了该课程,什么时候 - 它有双重职责。
    【解决方案2】:

    标志是多余的。另一种如何获得员工最后参加日的方法:

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

    【讨论】:

      【解决方案3】:

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

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

      例如SELECT YEAR(2008-01-01) 将返回 2008 作为整数。

      【讨论】:

      • Matt - 我将日期存储为日期时间数据类型。对于我在帖子中输入日期的方式感到困惑,我们深表歉意
      【解决方案4】:

      如果您运行的是 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) 之类的语句的存储过程可能会更有效。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-01
        相关资源
        最近更新 更多