2011-12-30 1 views
4

Так я следующее заявление я выполняющийся в Microsoft SQL 2008:Параметры в нечетных местах в Подготовленные отчетности в Microsoft SQL и JDBC

SELECT 
    'UTC' AS timezone, 
    rel.unique_id AS relay,sns.unique_id AS sensor, 
    dateadd(MINUTE, datediff(MINUTE, 0, pak.rtime)/? * ?, 0) AS time, 
    SUM(CONVERT(FLOAT,dat.data)) AS total 
    FROM sensor_data dat 
    LEFT OUTER JOIN data_package pak ON dat.package_id = pak.id 
    LEFT OUTER JOIN relays rel ON pak.relay_id = rel.id 
    LEFT OUTER JOIN sensors sns ON dat.sensor_id = sns.id 
    LEFT OUTER JOIN sensor_types typ ON sns.sensor_type = typ.id 
    WHERE typ.name = 'Volume' AND dateadd(MINUTE, datediff(MINUTE, 0, pak.rtime)/? * ?, 0) > ? AND dateadd(MINUTE, datediff(MINUTE, 0, pak.rtime)/? * ?, 0) < ? 
    GROUP BY rel.unique_id,sns.unique_id, dateadd(MINUTE, datediff(MINUTE, 0, pak.rtime)/? * ?, 0) 
    ORDER BY time,relay,sensor 

Если установить параметры с помощью jTDS/драйвер JDBC, как так :

Parameter 1: 15 
Parameter 2: 15 
Parameter 3: 15 
Parameter 4: 15 
Parameter 5: 2011-10-31 20:00:00 
Parameter 6: 15 
Parameter 7: 15 
Parameter 8: 2011-12-29 19:00:00 
Parameter 9: 15 
Parameter 10: 15 

Я получаю ошибку:

Caused by: java.sql.SQLException: Column 'data_package.rtime' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. 

Если я вручную поместить в 15s во всех тех, кто? пробелы, запрос работает отлично с датами в качестве параметров.

1) Нужно ли в любом случае параметризовать значение интервала (в данном случае 15), или мне просто нужно его избежать и выполнить поиск и замену, прежде чем он станет подготовленным оператором (и если это правда, что это лучший способ избегайте этого параметра в Scala/Java)

2) Могу ли я повторять трижды задание dateadd (датированный())? Я знаю, что не могу ссылаться на «время» в предложении WHERE, но есть ли другой способ указать, что где-нибудь сделать его более чистым?

ответ

5

селектов выглядит как:

SELECT dateadd(MINUTE, datediff(MINUTE, 0, pak.rtime)/? * ?, 0) AS time, 

и ваша группа по:

GROUP BY dateadd(MINUTE, datediff(MINUTE, 0, pak.rtime)/? * ?, 0) 

С ? заменены константами, эти два являются идентичными.

Но использование неназванных параметров создает проблему. Версия выбора использует параметры 1 и 2, а группа по версии использует параметры 9 и 10. И SQL Server теперь не так, что эти параметры всегда равны. Поэтому он выдает ошибку.

Вы можете избежать этой ситуации путем вычисления поля в подзапрос:

left join 
     (
     select * 
     ,  dateadd(MINUTE, datediff(MINUTE, 0, pak.rtime)/? * ?, 0) as X 
     from data_package 
     ) as pak 
on  dat.package_id = pak.id 

Теперь вы можете обратиться к pak.X в других частях вашего запроса, например:

group by 
     pak.X 
+0

Не нужно использовать подзапрос, производная таблица должна быть в порядке –

+0

@a_horse_with_no_name: В чем разница между производной таблицей и подзапросом? – Andomar

0

Andomar прав, что проблема заключается в использовании параметров в вашей GROUP BY, но я считаю, что его решение может быть чрезмерно сложным. Легче, я бы, чтобы написать:

SELECT 
    'UTC' AS timezone, 
    rel.unique_id AS relay,sns.unique_id AS sensor, 
    dateadd(MINUTE, datediff(MINUTE, 0, pak.rtime)/? * ?, 0) AS time, 
    SUM(CONVERT(FLOAT,dat.data)) AS total 
    FROM sensor_data dat 
    LEFT OUTER JOIN data_package pak ON dat.package_id = pak.id 
    LEFT OUTER JOIN relays rel ON pak.relay_id = rel.id 
    LEFT OUTER JOIN sensors sns ON dat.sensor_id = sns.id 
    LEFT OUTER JOIN sensor_types typ ON sns.sensor_type = typ.id 
    WHERE typ.name = 'Volume' AND dateadd(MINUTE, datediff(MINUTE, 0, pak.rtime)/? * ?, 0) > ? AND dateadd(MINUTE, datediff(MINUTE, 0, pak.rtime)/? * ?, 0) < ? 
    GROUP BY rel.unique_id,sns.unique_id, time 
    ORDER BY time,relay,sensor 

(С другой стороны, так как в вашем конкретном случае, вы используете один и тот же выражение в WHERE, может быть подзапрос бы быть лучше.)

Смежные вопросы