2017-03-07 4 views
1

これは期待通りに動作している:なぜORDER BY DATEDIFFがJPAを使用してSQLサーバーで例外を発生させるのですか?

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節にあるものだけを選択しています。そして、日付は同じです:それは同じインスタンスです!

+0

はあなたが試すことができます>> GROUP:

あなたはとてもグループ化し、その結果は同じ中間値を使用することができ、ネストされた文の式を計算する必要があります) –

答えて

2

JPAに精通していない、私は確かに言うことはできませんが、私はそれらの?はそうあなたGROUP BYはあなたのSELECTよりも異なるだろう、それはSQL Serverになり、時間によって@P1@P2に展開ます推測しています。

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) 
+0

興味深い!つまり、JPAの実装(私の場合はHibernate)で実際に問題が起こっている(または修正される可能性がある)ということです。私は試してみます... – Dush

2

クエリが(?)をパラメーター・マーカーを使用しているため、SQL Optimizerは、両方のマーカーが同じ値を持っていることを知ることができないので、結果式:あなたのSQLステートメントは、おそらくSQL Serverに次のようになります

グループ化の表現とは異なるとみなされます。 ?DATEDIFF(週、CREATION_DATEをHAVING CREATION_DATE BY

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 
) 
+0

MySQLとHSQLDBのために、同じコードが動作しています。しかし、私はあなたが正しいと思う、それはSQL Serverのための最良のソリューションです。それだけで私のすでに複雑で動的に生成されたクエリを助けるつもりはない... – Dush

関連する問題