2012-12-03 126 views
0

我有一个T-SQL查询,旨在清除某些产品培训的重复条目,只抓取具有最新DateTaken的条目。例如,如果有人已经进行了三次特定的培训课程,我们只想显示一行,该行是包含最近DateTaken的那一行。以下是我迄今为止,但我收到以下错误:选择最近的日期群组

An expression of non-boolean type specified in a context where a condition is expected, near '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管理Studio,红线错误标记出现在p.ProductDescription后面的',',c.CourseDescription后的')',.DateTaken中的'a'以及GETUTCDATE()的右括号')'下。如果我只是离开GROUP BY语句,只包括p.ProductDescription我收到此错误信息:

Column 'Product.ProductDescription' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

我是比较新的SQL,可能有人解释这是怎么回事?谢谢!

+7

[不良习惯踢:使用旧样式的JOIN(http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/bad-habits -to-kick-using-old-style-joins.aspx) - 旧式*逗号分隔的表*样式列表已停止使用ANSI-** 92 ** SQL标准(** 20年前** !)。 ***请***停止使用它 –

+0

标题要求最早的日期 - 问题要求最新。请更正其中之一。猜题目。 –

+0

问题陈述涉及“最近的DateTaken”,而标题和TSQL似乎最少要寻找。 – HABO

回答

4

我的建议,因为你正在使用SQL Server是执行row_number()并由ProductDescriptionCourseDescription分区。这将大大子查询,然后应用过滤器只在该行数等于一个或最近的记录返回那些:

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 
3

其此行

HAVING MIN(a.DateTaken) 

应该是一个boolean类型,如

HAVING MIN(a.DateTaken) > GETUTCDATE() 

必须返回真或假(布尔)

+0

不幸的是这会返回以下错误:“列”产品。ProductDescription'在选择列表中是无效的,因为它不包含在聚合函数或GROUP BY子句中。“ – NealR

+0

@NealR添加一个group by子句和不想聚合的字段 – AbstractChaos

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' 
+1

是否有原因你想使用逗号分隔的表格列表,而不是使用ANSI JOIN语法和'INNER JOIN'? – Taryn

+0

不,这只是我在学校学到的synatx。 – NealR

+1

[踢坏的习惯:使用旧式的JOIN]( http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/bad-habits-to-kick-using-old-style-joins.aspx) - 旧样式逗号分隔的表格样式列表已经停止使用ANSI-92 SQL标准(20年前) – Taryn