Hibernate SQLServer2017列在选择列表中无效,因为该列未包含在聚合函数或GROUP BY子句中

时间:2019-04-11 04:58:32

标签: sql spring hibernate spring-boot jdbc

好吧,我正在使用hibernate在SpringBoot应用程序中运行以下SQL本机查询,请注意,该查询在Sql Management Studio中运行良好,并返回了一些结果。在我的IDE中,我可以使用JDBC驱动程序连接到我的SQL Server 2017,并且仍然可以运行此查询并返回一些结果,现在出现了一个奇怪的部分,当在应用程序中运行相同的查询时,出现以下错误:< / p>

选择列表中的“ 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();
  }

以下用于测试SQL有效性的简单Java程序运行正常:

        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 个答案:

答案 0 :(得分:1)

所以我弄清楚了为什么我的查询失败:实际的查询是这样的:

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

然后我用实际的分钟数替换了{periodInterval}的纯正的Java字符串,生成的sql仅带有:startTime和:endTime参数,我在休眠中使用了它,一切都很好。

答案 1 :(得分:0)

尝试一下

logvol /

注意::我没有SQLServer,也没有在其他任何数据库上使用它。尽管如此,它应该按原样运行。如果不是,则可能需要一些较小的语法修复。但是,结果应该是预期的结果。无论如何,它肯定会给您这个想法。希望是好的。