Параметры в нечетных местах в подготовленных выражениях в Microsoft SQL и JDBC - PullRequest
4 голосов
/ 31 декабря 2011

Итак, у меня есть следующее утверждение, которое я выполняю в Microsoft SQL 2008:

  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.

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

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

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

Ответы [ 2 ]

5 голосов
/ 31 декабря 2011

Ваш выбор выглядит так:

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 голосов
/ 31 декабря 2011

Андомар прав, что проблема заключается в использовании параметров в вашем 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, возможно, подзапрос будет будь лучше.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...