Hibernate SQLServer2017 Столбец недопустим в списке выбора, потому что он не содержится ни в статистической функции, ни в предложении GROUP BY - PullRequest
1 голос
/ 11 апреля 2019

Хорошо. Я запускаю собственный SQL-запрос ниже в моем приложении SpringBoot с помощью hibernate, обратите внимание, что этот запрос работает нормально в Sql Management Studio и возвращает некоторые результаты.В моей среде IDE я могу использовать драйвер JDBC для подключения к своему SQL-серверу 2017, и я все еще могу выполнить этот запрос и вернуть некоторые результаты. Теперь возникает странная часть: когда тот же запрос выполняется внутри приложения, я получаю следующую ошибку:

Столбец ESB_TRANSACTION.time_in недопустим в списке выбора, поскольку он не содержится ни в статистической функции, ни в предложении GROUP BY

Вот запрос:

SELECT
        CASE WHEN (suc.transaction_time IS NOT NULL) THEN suc.transaction_time ELSE err.transaction_time END as transaction_time,
        CASE WHEN (suc.success_count IS NOT NULL) THEN suc.success_count ELSE 0 END as success_count,
        CASE WHEN (err.error_count IS NOT NULL) THEN err.error_count ELSE 0 END as error_count
FROM
  (
    SELECT
          COUNT(et.status) error_count,
          DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, 0, et.time_in) / 1440) * 1440, 0) AS transaction_time
    FROM
          ESB_TRANSACTION et
    WHERE
          (et.status='ERROR')  AND (et.time_in BETWEEN '2019-01-01 00:00:00' AND '2019-12-12 23:59:59')
    GROUP BY DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, 0, et.time_in) / 1440) * 1440, 0)
  ) err
  RIGHT OUTER JOIN (
    SELECT
          COUNT(et.status) success_count,
          DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, 0, et.time_in) / 1440) * 1440, 0) AS transaction_time
    FROM
          ESB_TRANSACTION et
    WHERE
          (et.status='SUCCESS')  AND (et.time_in BETWEEN '2019-01-01 00:00:00' AND '2019-12-12 23:59:59')
    GROUP BY DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, 0, et.time_in) / 1440) * 1440, 0)
  ) suc ON err.transaction_time = suc.transaction_time
  ORDER BY transaction_time ASC

Как именно я должен это решить?

Вот соответствующий код Java:

`public List execute(final String query, final DateRange selectedRange, final int minutes) {
    return (List) repository.getEntityManager()
            .createNativeQuery(query)
            .setParameter("startTime", selectedRange.getFrom())
            .setParameter("endTime", selectedRange.getTo())
            .setParameter("periodInterval", minutes   )
            .getResultList();
  }

Следующая простая программа Java, чтобы проверить правильностьSQL работает нормально:

        try (Connection con = DriverManager.getConnection(connectionUrl); Statement stmt = con.createStatement();) {
          String contents = new String(Files.readAllBytes(Paths.get("C:\\Temp\\mssqlserver.sql")));
            ResultSet rs = stmt.executeQuery(contents);
            while (rs.next()) {
                System.out.println(rs.getString("transaction_time") + " =>" + rs.getInt("success_count") +" =>"+ rs.getInt("error_count"));
            }
        }
        catch (IOException | SQLException e) {
            e.printStackTrace();
        }

Я действительно получаю правильный вывод, так что не так с моим Spring Boot + Hibernate?

Ответы [ 2 ]

1 голос
/ 15 апреля 2019

Итак, я выяснил, почему мой запрос не удался: фактический запрос был таким:

SELECT
        CASE WHEN (suc.transaction_time IS NOT NULL) THEN suc.transaction_time ELSE err.transaction_time END as transaction_time,
        CASE WHEN (suc.success_count IS NOT NULL) THEN suc.success_count ELSE 0 END as success_count,
        CASE WHEN (err.error_count IS NOT NULL) THEN err.error_count ELSE 0 END as error_count
FROM
  (
    SELECT
          COUNT(et.status) error_count,
          DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, 0, et.time_in) / :periodInterval) * :periodInterval, 0) AS transaction_time
    FROM
          ESB_TRANSACTION et
    WHERE
          (et.status='ERROR')  AND (et.time_in BETWEEN :startTime AND :endTime)
    GROUP BY DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, 0, et.time_in) / :periodInterval) * :periodInterval, 0)
  ) err
  RIGHT OUTER JOIN (
    SELECT
          COUNT(et.status) success_count,
          DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, 0, et.time_in) / :periodInterval) * :periodInterval, 0) AS transaction_time
    FROM
          ESB_TRANSACTION et
    WHERE
          (et.status='SUCCESS')  AND (et.time_in BETWEEN :startTime AND :endTime)
    GROUP BY DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, 0, et.time_in) / :periodInterval) * :periodInterval, 0)
  ) suc ON err.transaction_time = suc.transaction_time
  ORDER BY transaction_time ASC

параметры: periodInterval, startTime и endTime, добавленные во время выполнения, это было единственное различие между SQLзапрос во время выполнения и другие, которые я выполнял ... поэтому я решил манипулировать запросом sql перед его выполнением:

SELECT
        CASE WHEN (suc.transaction_time IS NOT NULL) THEN suc.transaction_time ELSE err.transaction_time END as transaction_time,
        CASE WHEN (suc.success_count IS NOT NULL) THEN suc.success_count ELSE 0 END as success_count,
        CASE WHEN (err.error_count IS NOT NULL) THEN err.error_count ELSE 0 END as error_count
FROM
  (
    SELECT
          COUNT(et.status) error_count,
          DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, 0, et.time_in) / {periodInterval}) * :periodInterval, 0) AS transaction_time
    FROM
          ESB_TRANSACTION et
    WHERE
          (et.status='ERROR')  AND (et.time_in BETWEEN :startTime AND :endTime)
    GROUP BY DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, 0, et.time_in) / {periodInterval}) * {periodInterval}, 0)
  ) err
  RIGHT OUTER JOIN (
    SELECT
          COUNT(et.status) success_count,
          DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, 0, et.time_in) / {periodInterval}) * {periodInterval}, 0) AS transaction_time
    FROM
          ESB_TRANSACTION et
    WHERE
          (et.status='SUCCESS')  AND (et.time_in BETWEEN :startTime AND :endTime)
    GROUP BY DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, 0, et.time_in) / {periodInterval}) * {periodInterval}, 0)
  ) suc ON err.transaction_time = suc.transaction_time
  ORDER BY transaction_time ASC

, затем я заменил прямую строку Java для {periodInterval} фактическимминут, полученный SQL-файл содержит только параметры: startTime и: endTime. Я использовал его в режиме гибернации, и все было хорошо.

0 голосов
/ 11 апреля 2019

Попробуйте это,

SELECT
    CASE WHEN (suc.transaction_time IS NOT NULL) THEN suc.transaction_time ELSE err.transaction_time END as transaction_time,
    CASE WHEN (suc.success_count IS NOT NULL) THEN suc.success_count ELSE 0 END as success_count,
    CASE WHEN (err.error_count IS NOT NULL) THEN err.error_count ELSE 0 END as error_count
FROM
    (
    SELECT
         COUNT(et.status) error_count, et.time_in AS transaction_time
    FROM
        (
        SELECT
            eti.status,
            DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, 0, eti.time_in) / 1440) * 1440, 0) AS time_in
        FROM ESB_TRANSACTION eti
        WHERE
            (eti.status='ERROR')  AND (eti.time_in BETWEEN '2019-01-01 00:00:00' AND '2019-12-12 23:59:59')
        ) et    
    GROUP BY et.time_in
    ) err
RIGHT OUTER JOIN
    (
    SELECT
          COUNT(et.status) success_count, et.time_in AS transaction_time
    FROM
        (
        SELECT eti.status,
               DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, 0, eti.time_in) / 1440) * 1440, 0) AS time_in
        FROM ESB_TRANSACTION eti
        WHERE
            (eti.status='SUCCESS')  AND (eti.time_in BETWEEN '2019-01-01 00:00:00' AND '2019-12-12 23:59:59')
        ) et    
    GROUP BY et.time_in
    ) suc  ON err.transaction_time = suc.transaction_time
ORDER BY transaction_time ASC

Примечание: У меня нет SQLServer, и я не попробовал ни одну другую БД. Тем не менее, он должен работать так, как есть; если нет, то, вероятно, это может потребовать небольшого исправления синтаксиса. Однако результат должен быть ожидаемым. В любом случае, это, безусловно, даст вам идею. Надеемся навсегда.

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