Java 为什么ORDER BY DATEDIFF在使用JPA的SQL server上引发异常?

Java 为什么ORDER BY DATEDIFF在使用JPA的SQL server上引发异常?,java,sql-server,hibernate,jpa,Java,Sql Server,Hibernate,Jpa,这是预期的工作: jdbcTemplate.query( "select datediff(week, '2017-01-02', creation_date), count(*) from somewhere group by datediff(week, '2017-01-02', creation_date)", new RowMapper() { Object mapRow(ResultSet rs, int rowNum) thr

这是预期的工作:

jdbcTemplate.query(
        "select datediff(week, '2017-01-02', creation_date), count(*) from somewhere group by datediff(week, '2017-01-02', creation_date)",
        new RowMapper() {
            Object mapRow(ResultSet rs, int rowNum) throws SQLException {
                return [rs.getObject(1), rs.getObject(2)]
            }
        }
)
但当我运行下面的查询时,会出现此异常:

SQLServerException: Column 'somewhere.creation_date' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
查询:

def date = new Date(117, 0, 2)
jdbcTemplate.query(
        "select datediff(week, ?, creation_date), count(*) from somewhere group by datediff(week, ?, creation_date)",
        new RowMapper() {
            Object mapRow(ResultSet rs, int rowNum) throws SQLException {
                return [rs.getObject(1), rs.getObject(2)]
            }
        },
        date,
        date
)
JPA实现是Hibernate 5.0.11。 我使用Spring和Groovy进行演示,但实际的代码是纯java+JPA标准,显然存在相同的问题


为什么这不起作用?我只选择Group By子句中的内容。日期是一样的:甚至是同一个实例

不熟悉JPA,我不能肯定,但我猜是吧?在@P1和@P2进入SQL Server时,将其扩展到@P1和@P2,这样您的分组方式将不同于您选择的分组方式

对于SQL Server,您的SQL语句可能如下所示:

SELECT @P1 = '2017-01-02', @P2 = '2017-01-02';
select datediff(week, @P1, creation_date), count(*) 
from somewhere 
group by datediff(week, @P2, creation_date)

不熟悉JPA,我不能肯定,但我猜这些?在@P1和@P2进入SQL Server时,将其扩展到@P1和@P2,这样您的分组方式将不同于您选择的分组方式

对于SQL Server,您的SQL语句可能如下所示:

SELECT @P1 = '2017-01-02', @P2 = '2017-01-02';
select datediff(week, @P1, creation_date), count(*) 
from somewhere 
group by datediff(week, @P2, creation_date)

由于查询使用参数标记?,SQL优化器无法知道两个标记将具有相同的值,因此结果表达式被认为与分组表达式不同

您需要在嵌套语句中计算表达式,以便分组和结果可以使用相同的中间值:

def date = new Date(117, 0, 2)
jdbcTemplate.query(
        "select weekdiff, count(*)" +
         " from ( select datediff(week, ?, creation_date) as weekdiff" +
                  " from somewhere" +
              " ) x" +
        " group by weekdiff",
        new RowMapper() {
            Object mapRow(ResultSet rs, int rowNum) throws SQLException {
                return [rs.getObject(1), rs.getObject(2)]
            }
        },
        date
)

由于查询使用参数标记?,SQL优化器无法知道两个标记将具有相同的值,因此结果表达式被认为与分组表达式不同

您需要在嵌套语句中计算表达式,以便分组和结果可以使用相同的中间值:

def date = new Date(117, 0, 2)
jdbcTemplate.query(
        "select weekdiff, count(*)" +
         " from ( select datediff(week, ?, creation_date) as weekdiff" +
                  " from somewhere" +
              " ) x" +
        " group by weekdiff",
        new RowMapper() {
            Object mapRow(ResultSet rs, int rowNum) throws SQLException {
                return [rs.getObject(1), rs.getObject(2)]
            }
        },
        date
)

您可以尝试>>按创建分组吗?日期为datediffweek,?创建日期?您可以尝试>>按创建分组吗?日期为datediffweek,?创建日期?相同的代码适用于MySQL和HSQLDB。但我认为你是对的,这是SQL Server的最佳解决方案。这对我已经复杂的、动态生成的查询毫无帮助……好吧,同样的代码也适用于MySQL和HSQLDB。但我认为你是对的,这是SQL Server的最佳解决方案。这对我已经复杂且动态生成的查询毫无帮助……很有趣!这意味着这个问题实际上即将出现,或者在我的例子中,可以在JPA实现Hibernate中修复。我试试……有趣!这意味着这个问题实际上即将出现,或者在我的例子中,可以在JPA实现Hibernate中修复。我试试。。。