2

次のようなデータがあります。

  sensorid |  sampletime             |  correctedvalue   | qualityflag
-----------------------------------------------------------------------
  4472     | 27-OCT-10 00:00:00.123  |   3.75            | 0
  4472     | 27-OCT-10 00:00:01.324  |   3.85            | 0
  4472     | 27-OCT-10 00:00:02.123  |   3.92            | 0
  4472     | 27-OCT-10 00:00:03.324  |   4.05            | 0

また、Oracle SQL Developerで正常に機能するクエリ(15秒間の平均データを返します):

select sensorid,
    trunc(sampletime,'hh24') + 
    (trunc(to_char(sampletime,'mi')))/24/60 +
    (trunc(to_char(sampletime,'ss')/15)*15)/24/60/60 as tspan, 
    avg(correctedvalue),
    max(qualityflag)
from scalarsample
group by sensorid, 
    trunc(sampletime,'hh24') + 
    (trunc(to_char(sampletime,'mi')))/24/60 +
    (trunc(to_char(sampletime,'ss')/15)*15)/24/60/60
order by tspan

しかし、Javaコードにプラグインすると、エラーが発生します。

org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.loader.Loader.doList(Loader.java:2223)
...
Caused by: java.sql.SQLSyntaxErrorException: ORA-00979: not a GROUP BY expression

at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:221)
at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:118)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:224)
...

Javeで使用する実際のクエリ文字列は、次のようになります。

select sensorid,
    trunc(sampletime,'hh24') + 
    (trunc(to_char(sampletime,'mi')))/24/60 +
    (trunc(to_char(sampletime,'ss')/?)*?)/24/60/60 as tspan, 
    avg(correctedvalue),
    max(qualityflag)
from scalarsample
where sampletime between ? and ?
    and sensorid = ?
group by sensorid, 
    trunc(sampletime,'hh24') + 
    (trunc(to_char(sampletime,'mi')))/24/60 +
    (trunc(to_char(sampletime,'ss')/?)*?)/24/60/60
order by tspan

パラメータは、次を呼び出すことによって設定されます。

SQLQuery q = session.createSQLQuery(queryString);
q.setInteger(0, averagingWindowInSeconds);
q.setInteger(1, averagingWindowInSeconds);
q.setTimestamp(2, dateFrom);
q.setTimestamp(3, dateTo);
q.setInteger(4, sensorId);
q.setInteger(5, averagingWindowInSeconds);
q.setInteger(6, averagingWindowInSeconds);
q.addEntity(ScalarSampleState.class);

この「GROUPBY式ではありません」エラーが発生する理由を知っている人はいますか?

私はここでトムから時間間隔で平均化を行うこの方法を選びました:http://asktom.oracle.com/pls/apex/f?p = 100:11:0 :::: P11_QUESTION_ID: 4222062043865

編集 それはほとんど次のように解決されたようです:

select sensorid,
    trunc(sampletime,'hh24') + 
    (trunc(to_char(sampletime,'mi')))/24/60 +
    (trunc(to_char(sampletime,'ss')/?)*?)/24/60/60 as sampletime, 
    avg(correctedvalue),
    max(qualityflag)
from scalarsample
where sampletime between ? and ?
    and sensorid = ?
group by sensorid, sampletime
order by sampletime

注: sampletimeを使用して、テーブルの列の1つの名前である列の名前を変更しました。sampletimeの代わりに「tspan」という名前では機能しません。

ORA-00904: "TSPAN": invalid identifier
00904. 00000 -  "%s: invalid identifier"

新しい列にsampletimeという名前を付け、GROUP BY句でsampletimeを使用すると、そのエラーはなくなり、SQLDeveloperでクエリが完全に実行されました。残念ながら、Javaから実行すると、サンプル時間ごとに複数の同一の行が返されました。Grrrr...。

解決策:以下で選択した解決策が機能しました。文字列を読みやすくするために、文字列を引用符とプラス記号で囲みました。

SELECT
    sensorid, 
    TRUNC( sampletime, hh24) +
    (TRUNC(to_char(sampletime,'mi')))/24/60 +
    (TRUNC(to_char(sampletime,'ss')//averagingWindowInSeconds )*averagingWindowInSeconds)/24/60/60 as sampletime,
    AVG( correctedvalue) as correctedvalue, 
    MAX(qualityflag)
FROM scalarsample
WHERE 
    sampletime BETWEEN ? AND ?
    AND sensorid = ?
GROUP BY sensorid,
    TRUNC( sampletime, hh24) +
    (TRUNC(to_char(sampletime,'mi')))/24/60 +
    (TRUNC(to_char(sampletime,'ss')//averagingWindowInSeconds 
ORDER BY sampletime ";  
4

1 に答える 1

3

JDBCドライバーは、「?」ごとに一意のバインド変数名を作成しているようです。残念ながら、Oracleでは、group by句はselect句と文字ごとに一致する必要がありますが、このため、一致しません。Oracleでデータを使用してテーブルをモックアップし、動的SQLとバインド変数を使用していくつかのテストクエリを実行しました。まず、順番に名前が付けられたバインド変数を使用します。

SQL> l
  1  declare
  2  cur sys_refcursor;
  3  begin
  4  open cur for 'select sensorid, ' ||
  5  '    trunc(sampletime,''hh24'') +  ' ||
  6  '    (trunc(to_char(sampletime,''mi'')))/24/60 + ' ||
  7  '    (trunc(to_char(sampletime,''ss'')/:b1)*:b2)/24/60/60 as tspan,  ' ||
  8  '    avg(correctedvalue), ' ||
  9  '    max(qualityflag) ' ||
 10  'from scalarsample ' ||
 11  'where sampletime between DATE ''2010-10-27'' and DATE ''2010-10-28'' ' ||
 12  '    and sensorid = 4472 ' ||
 13  'group by sensorid,  ' ||
 14  '    trunc(sampletime,''hh24'') +  ' ||
 15  '    (trunc(to_char(sampletime,''mi'')))/24/60 + ' ||
 16  '    (trunc(to_char(sampletime,''ss'')/:b3)*:b4)/24/60/60 ' ||
 17  'order by tspan'
 18  using 15, 15, 15, 15;
 19  close cur;
 20* end;

結果:

SQL> @test
declare
*
ERROR at line 1:
ORA-00979: not a GROUP BY expression
ORA-06512: at line 4

次に、同じ名前のバインド変数を使用します。

SQL> l
  1  declare
  2  cur sys_refcursor;
  3  begin
  4  open cur for 'select sensorid, ' ||
  5  '    trunc(sampletime,''hh24'') +  ' ||
  6  '    (trunc(to_char(sampletime,''mi'')))/24/60 + ' ||
  7  '    (trunc(to_char(sampletime,''ss'')/:b1)*:b1)/24/60/60 as tspan,  ' ||
  8  '    avg(correctedvalue), ' ||
  9  '    max(qualityflag) ' ||
 10  'from scalarsample ' ||
 11  'where sampletime between DATE ''2010-10-27'' and DATE ''2010-10-28'' ' ||
 12  '    and sensorid = 4472 ' ||
 13  'group by sensorid,  ' ||
 14  '    trunc(sampletime,''hh24'') +  ' ||
 15  '    (trunc(to_char(sampletime,''mi'')))/24/60 + ' ||
 16  '    (trunc(to_char(sampletime,''ss'')/:b1)*:b1)/24/60/60 ' ||
 17  'order by tspan'
 18  using 15, 15, 15, 15;
 19  close cur;
 20* end;

結果:

SQL> @test
PL/SQL procedure successfully completed.

したがって、averagingWindowInSecondsこれらの4つのバインド変数を使用する代わりに、値をクエリに連結してみてください。

于 2012-11-28T23:08:20.263 に答える