从组中选择最近的日期

时间:2012-12-03 17:51:37

标签: sql-server tsql

我有一个T-SQL查询,旨在清除某个产品培训的重复条目,只获取具有最新DateTaken的条目。例如,如果某人已经参加了3次特定的培训课程,我们只想显示一行,该行是包含最新DateTaken的行。这是我到目前为止,但是我收到以下错误:

  

在“ORDER”附近的预期条件的上下文中指定的非布尔类型的表达式。

ORDER BY是必要的,因为我们希望在截止日期之前将此查询的所有结果分组。以下是完整查询:

SELECT DISTINCT 
   p.ProductDescription as ProductDesc, 
   c.CourseDescription as CourseDesc, 
   c.Partner, a.DateTaken, a.DateExpired, p.Status 
FROM 
   sNumberToAgentId u, AgentProductTraining a, Course c, Product p 
WHERE 
    @agentId = u.AgentId 
    and u.sNumber = a.sNumber 
    and a.CourseCode = c.CourseCode 
    and (a.DateExpired >= @date or a.DateExpired IS NULL) 
    and a.ProductCode  = p.ProductCode 
    and (p.status != 'D' or p.status IS NULL)
GROUP BY
    (p.ProductDescription) 
HAVING 
    MIN(a.DateTaken)
ORDER BY 
    DateExpired ASC

修改

我对GROUP BY和HAVING子句进行了以下更改,但是我仍然收到错误:

GROUP BY
    (p.ProductDescription, c.CourseDescription) 
HAVING 
    MIN(a.DateTaken) > GETUTCDATE()

在SQL Management Studio中,红线错误标记出现在p.ProductDescription之后的','之后,c.CourseDescription之后的')',a.DateTaken中的'a'和右括号')' GETUTCDATE()。如果我只是将GROUP BY语句保留为仅包含p.ProductDescription,则会收到以下错误消息:

  

列'Product.ProductDescription'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。

我对SQL比较陌生,有人可以解释发生了什么吗?谢谢!

3 个答案:

答案 0 :(得分:5)

我建议你使用sql server是为了实现row_number()并按ProductDescriptionCourseDescription进行分区。这将进入子查询,然后应用过滤器仅返回行号等于1或最近记录的那些:

select *
from
(
    SELECT   p.ProductDescription as ProductDesc, 
       c.CourseDescription as CourseDesc, 
       c.Partner, a.DateTaken, a.DateExpired, p.Status 
       row_number() over(partition by p.ProductDescription, c.CourseDescription order by a.DateTaken desc) rn
    FROM sNumberToAgentId u
    INNER JOIN AgentProductTraining a
        ON u.sNumber = a.sNumber 
        AND (a.DateExpired >= @date or a.DateExpired IS NULL) 
    INNER JOIN Course c
        ON a.CourseCode = c.CourseCode 
    INNER JOIN Product p 
        ON a.ProductCode  = p.ProductCode 
        AND (p.status != 'D' or p.status IS NULL)
    WHERE  u.AgentId = @agentId
) src
where rn = 1
order by DateExpired

答案 1 :(得分:3)

这一行

HAVING MIN(a.DateTaken)

应该是布尔类型,例如

  HAVING MIN(a.DateTaken) > GETUTCDATE()

必须返回True或False(布尔值)

答案 2 :(得分:0)

这是我最后使用的查询。它类似于上面的建议:

SELECT ProductDesc, CourseDesc, Partner, DateTaken, DateExpired, Status
FROM(
    SELECT  
       p.ProductDescription as ProductDesc, 
       c.CourseDescription as CourseDesc, 
       c.Partner, a.DateTaken, a.DateExpired, p.Status,
       row_number() OVER (PARTITION BY p.ProductDescription, c.CourseDescription ORDER BY abs(datediff(dd, DateTaken, GETDATE()))) as Ranking
    FROM 
        sNumberToAgentId u, AgentProductTraining a, Course c, Product p 
    WHERE 
        @agentId = u.AgentId 
        and u.sNumber = a.sNumber 
        and a.CourseCode = c.CourseCode 
        and (a.DateExpired >= @date or a.DateExpired IS NULL) 
        and a.ProductCode  = p.ProductCode 
        and (p.status != 'D' or p.status IS NULL)
    ) aa
WHERE Ranking = '1'