开发者

Ordering by a Column that's not in the Group By or Enapsulated in an Aggregate

开发者 https://www.devze.com 2022-12-14 12:17 出处:网络
I have a problem getting this JPA query to work on MS SQL Server 2008. The background is as follows: Users create jobs for clients, of which there a开发者_StackOverflow中文版re many. I am displaying

I have a problem getting this JPA query to work on MS SQL Server 2008.

The background is as follows: Users create jobs for clients, of which there a开发者_StackOverflow中文版re many. I am displaying a list of his most recently used clients to the user to make the selection easier.

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

The query works just fine - using MySQL. MS SQL Server (2008) complains that I cannot sort by j.created because it is not part of the select list. This is the error message:

ORDER BY items must appear in the select list if SELECT DISTINCT is specified.

I can't seem to find an elegant workaround for this limitation. Does anyone have an idea?


Because you are selecting a distinct c from many, Sql server won't know which j.created to order by. You can group by c and then use an aggregate to order by the min or max j.created. Something like...

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


This isn't a limitation of SQL. The problem is that the sort doesn't make sense in terms of your query. The Distinct operator is going to aggregate multiple values of C each of which might have a different create date. So in this situation how would SQL sort it?

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


May be this question is a bit old but I have found a easier workaround.

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

Adding the fetch keyword to the join with tell JPA to include fields in the join in the select statement so mssql would no longer complaint about it.


Duckworth's answer pretty much solved the problem, so this is only for reference.

This was my first attempt after reading duck's and John's answers:

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

But selecting the full entites directly does not play with the GROUP BY clause, and results in a SQLGrammarException.

Instead, I now get only the IDs using this query:

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

Then I only have to fetch the entities using the IDs.

Thanks, everybody!

0

精彩评论

暂无评论...
验证码 换一张
取 消