我在将此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是,则选择列表 指定。
我似乎找不到这种限制的优雅解决方法。有没有人有想法?
答案 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获取实体。
谢谢大家!