按集合中的不在Group By或Enapsulated中的列进行排序

时间:2009-12-17 17:12:27

标签: java sql-server hibernate jpa

我在将此JPA查询用于MS SQL Server 2008时遇到问题。

背景如下:用户为客户创建工作,其中有很多工作。我正在向用户显示他最近使用过的客户端列表,以便更轻松地进行选择。

SELECT DISTINCT c FROM Client c 
    JOIN c.jobs j 
    WHERE j.user = ?1 
    ORDER BY j.created DESC

查询工作得很好 - 使用MySQL。 MS SQL Server(2008)抱怨我无法按j.created排序,因为它不是选择列表的一部分。这是错误消息:

  

ORDER BY项目必须出现在   如果SELECT DISTINCT是,则选择列表   指定。

我似乎找不到这种限制的优雅解决方法。有没有人有想法?

4 个答案:

答案 0 :(得分:4)

因为你从许多人那里选择一个不同的c,所以Sql server不会知道哪个j.created来订购。您可以按c分组,然后使用聚合按最小或最大j.created排序。有点像...

SELECT c.col1, c.col2 
FROM Client c 
JOIN c.jobs j 
WHERE j.user = ?1 
Group by c.col1, c.col2
ORDER BY MIN(j.created) DESC

答案 1 :(得分:2)

这不是SQL的限制。问题是排序在查询方面没有意义。 Distinct运算符将聚合C的多个值,每个值可能具有不同的创建日期。那么在这种情况下SQL会如何排序呢?

C    Create  
1    1/1/2009  
2    3/1/2008  
1    12/2/2009  
9    4/1/2009  

答案 2 :(得分:1)

可能这个问题有点陈旧,但我找到了一个更简单的解决方法。

SELECT DISTINCT c FROM Client c 
    JOIN fetch c.jobs j 
    WHERE j.user = ?1 
    ORDER BY j.created DESC

fetch关键字添加到联接中,告诉JPA在select语句中包含联接中的字段,以便mssql不再抱怨它。

答案 3 :(得分:0)

达克沃斯的答案几乎解决了这个问题,所以这仅供参考。

这是我读完鸭子和约翰的答案后的第一次尝试:

SELECT c FROM Client c JOIN c.jobs j 
    WHERE j.user = ?1 
    GROUP BY c 
    ORDER BY MIN(j.created) DESC

但直接选择完整的entites不会与GROUP BY子句一起使用,并导致SQLGrammarException

相反,我现在只使用此查询获取ID:

SELECT c.id FROM Client c JOIN c.jobs j 
    WHERE j.user = ?1 
    GROUP BY c.id 
    ORDER BY MIN(j.created) DESC

然后我只需要使用ID获取实体。

谢谢大家!