代码之家  ›  专栏  ›  技术社区  ›  Henning

按聚合中不在Group By中或未封装的列排序

  •  1
  • Henning  · 技术社区  · 16 年前

    我在让这个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 因为它不是选择列表的一部分。这是错误消息:

    按项目排序必须出现在 如果select distinct为 明确规定。

    对于这个限制,我似乎找不到一个优雅的解决方法。有人有主意吗?

    4 回复  |  直到 11 年前
        1
  •  4
  •   John Lemp Chris Heald    16 年前

    因为您选择的是一个与许多不同的C,所以SQL Server不知道要按哪个J.创建订单。您可以按C分组,然后使用聚合按创建的最小值或最大值J排序。有点像…

    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
    
        2
  •  2
  •   JohnFx    16 年前

    这不是SQL的限制。问题是,就您的查询而言,这种排序没有意义。distinct运算符将聚合C的多个值,每个值可能具有不同的创建日期。在这种情况下,SQL将如何对其进行排序?

    C    Create  
    1    1/1/2009  
    2    3/1/2008  
    1    12/2/2009  
    9    4/1/2009  
    
        3
  •  1
  •   Quincy    11 年前

    也许这个问题有点老,但我找到了一个更简单的解决方法。

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

    添加 fetch 关键字到join with,告诉jpa在select语句的join中包含字段,所以 mssql 不会再抱怨了。

        4
  •  0
  •   Henning    16 年前

    达克沃斯的回答基本上解决了这个问题,所以这仅供参考。

    这是我读了杜克和约翰的答案后的第一次尝试:

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

    但是直接选择完整的实体并不能与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来获取实体。

    谢谢大家!