2012-12-03 125 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