【问题标题】:First Occurrence of Record by Date按日期记录的第一次出现
【发布时间】:2014-04-15 03:24:17
【问题描述】:

我正在尝试返回员工姓名和奖励日期如果他们在用户指定的日期之前没有先前的奖励日期(这些是表单上的字段,StartDateTxtEndDateTxt 可见下面),也就是他们的“第一次出现”。

示例(AwardTbl 仅为简单起见):

AwardDate   EmployeeID  PlanID   AwardedUnits
3/1/2005    100200         1          3
3/1/2008    100200         1          7
3/1/2005    100300         1          5
3/1/2013    100300         1          8

如果我在日期 1/1/2005 - 12/31/2005 之间运行查询,它将返回 3/1/2005100200100300。如果我在 1/1/2008-12/31/2008 之间运行查询,它不会返回任何内容,1/1/2013 - 12/31/2013 也是如此,因为这些员工已经有更早的奖励日期。

我尝试了几种不同的方法,结果有些奇怪。

SELECT x.AstFirstName ,
       x.AstLastName ,
       y.AwardDate ,
       y.AwardUnits ,
       z.PlanDesc
FROM (AssociateTbl AS x
      INNER JOIN AwardTbl AS y ON x.EmployeeID = y.EmployeeID)
INNER JOIN PlanTbl AS z ON y.PlanID = z.PlanID
WHERE y.AwardDate BETWEEN [Forms]![PlanFrm]![ReportSelectSbfrm].[Form]![StartDateTxt] And [Forms]![PlanFrm]![ReportSelectSbfrm].[Form]![EndDateTxt] ;

此查询不关心是否有以前的记录,我认为这就是我不确定如何缩小查询范围的地方。

我也试过了:

  1. Min(AwardDate)(没用)
  2. WHERE子句中按TOP 1 AwardDate ASC排序的子查询,只返回1条记录
  3. 一个DCount("*", "AwardTbl", "AwardDate < [Forms]![PlanFrm]![ReportSelectSbfrm].[Form]![StartDateTxt]") < 1(这也没有区分它是否是第一次出现的AwardDate)

请注意:这是 MS Access。没有ROW_NUMBER()CTE 功能。

【问题讨论】:

    标签: sql ms-access-2007


    【解决方案1】:

    如果在 Having 子句中按 EmployeeID 和您的日期范围分组并用作过滤器列表,则最低奖励日期将起作用:

    SELECT x.AstFirstName ,
           x.AstLastName ,
           y.AwardDate ,
           y.AwardUnits ,
           z.PlanDesc
    FROM  ((AssociateTbl AS x
        INNER JOIN AwardTbl AS y ON x.EmployeeID = y.EmployeeID)
        INNER JOIN (select a.EmployeeID,min(a.AwardDate) AS MinAwardDate
                    from AwardTbl AS a
                    group by a.EmployeeID
                    having ((min(a.awardDate)>=[Forms]![PlanFrm]![ReportSelectSbfrm].[Form]![StartDateTxt]
                        and min(a.awardDate)<[Forms]![PlanFrm]![ReportSelectSbfrm].[Form]![EndDateTxt]))
                   ) AS d on d.EmployeeID = x.EmployeeID
                       and d.MinAwardDate = y.AwardDate)
        INNER JOIN PlanTbl AS z ON y.PlanID = z.PlanID
    

    【讨论】:

    • 在我的帖子底部查看我的注释。这是 MS Access。
    • 是的,我能做到。我认为格式有点不同,但与其他主要数据库不同。
    • 我收到与 Rahul 代码相同的错误。Syntax error (missing operator in query expression x.EmployeeID = y.EmployeeID INNER JOIN PlanTbl AS z ON y.PlanID = z.PlanID
    • 嗯...您的原始代码没有出现该错误?我已更新 sql 以将 AwardDate 与 EmployeeID 一起加入,因此您只能获得第一个奖励日期的奖励记录。
    • 仍然出现错误。让我尝试添加关键字AS(Access中需要)
    【解决方案2】:

    像下面这样试试

    SELECT x.AstFirstName ,
           x.AstLastName ,
           y.AwardDate ,
           y.AwardUnits ,
           z.PlanDesc
    FROM (AssociateTbl AS x
    INNER JOIN AwardTbl AS y 
    ON x.EmployeeID = y.EmployeeID)
    INNER JOIN PlanTbl AS z 
    ON y.PlanID = z.PlanID
    WHERE y.AwardDate BETWEEN '1/1/2005' AND '12/31/2005'
    GROUP BY y.EmployeeID,
           x.AstFirstName ,
           x.AstLastName ,
           y.AwardDate ,
           y.AwardUnits ,
           z.PlanDesc
    HAVING COUNT(*) = 1
    

    【讨论】:

    • 我立即得到一个错误:Syntax error (missing operator) in query expression x.EmployeeID = y.EmployeeID INNER JOIN PlanTbl AS z ON y.PlanID = z.PlanID.
    • 另一个错误:您尝试执行的查询不包含指定表达式“AstFirstName”作为聚合函数的一部分。
    • 现在:条件表达式中的数据类型不匹配。
    • @Newbie,这是错误的,因为选择列表中包含的列在 group by 中不存在。现在应该好了。数据类型不匹配很可能是此行y.AwardDate BETWEEN '1/1/2005' AND '12/31/2005' 的原因。您可以将硬编码的日期替换为您自己的输入输出。
    • 我仍然收到数据类型不匹配错误。它没有提供除此之外的任何提示。
    【解决方案3】:

    我相信您需要一个嵌套选择。嵌套查询将使用 Min(awardDate) 进行选择,外部查询将过滤您想要的时间段。

    如果您在同一个查询中同时使用两者,它会在 Min(awardDate) 在您指定的时间向您返回 Min(awardDate) 之前过滤掉结果。

    select y.employeeId, y.awardDate from (
      select x.employeeId, min(x.awardDate) as awardDate 
        from AssociateTbl as x 
        group by x.employeeId) as y 
    where y.awardDate >= :startAwardDate and y.awardDate < :endAwardDate;
    

    【讨论】:

    • 是的,我认为我们意见一致。你知道我应该怎么做吗? (我不擅长 SQL)。
    • 根据您使用的数据库,语法可能会有些偏差,但一般来说,它应该看起来像这样 select y.employeeId, y.awardDate from ( select x.employeeId, min(x .awardDate) from AssociateTbl as x group by x.employeeId) as y where y.awardDate >= :startAwardDate and y.awardDate
    • 嗯。在第一个 SELECT 中无法识别 y.AwardDate
    • 抱歉,嵌套查询执行 min(x.awardDate) 而不将其重新标记为 AwardDate,因此如果您这样做 select x.employeeId, min(x.awardDate) as awardDate... 它应该可以工作 select y.employeeId, y.awardDate from ( select x.employeeId, min(x.awardDate) as awardDate from AssociateTbl as x group by x.employeeId) as y where y.awardDate &gt;= :startAwardDate and y.awardDate &lt; :endAwardDate;
    • @tony,尝试将您的代码示例从评论移至您的答案。这样一来,您就可以将它放在一个地方,并且将来人们不必通过评论线程来获得 zist。
    猜你喜欢
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-01
    相关资源
    最近更新 更多