【问题标题】:Why Hibernate HSQL Concat is not working for MSSQL?为什么 Hibernate HSQL Concat 不适用于 MSSQL?
【发布时间】:2020-03-30 10:28:04
【问题描述】:

所以,我在一个连接到不同引擎(MySql、Oracle、PostgreSQL 和 MS SQL)的项目中有 Hibernate 5.3.1,所以我不能使用本机查询。

假设我在一个表中有 3 条记录,它们都具有相同的日期时间,但我需要仅按日期(而不是时间)对它们进行分组。 例如,2019-12-04

我执行这个查询:

SELECT 
 CONCAT(year(tx.date_), month(tx.date_), day(tx.date_)),
 iss.code,
 COUNT(tx.id) 
FROM 
 tx_ tx 
JOIN 
 issuer_ iss 
ON 
 tx.id_issuer = iss.id  
GROUP BY 
 CONCAT(year(tx.date_), month(tx.date_), day(tx.date_)), iss.code

但是,当我测试它连接到 SQL SERVER 2017 时,它不是返回 20191204,而是返回 2035。在 Oracle 和 MySQL 中运行良好。

有人知道为什么会这样吗?我尝试了不同的方法,例如使用 + 而不是 CONCAT 但结果是一样的。

我也尝试将它们单独提取(没有连接),并且它们一直返回正确。问题是,我需要按完整日期对它们进行分组。

为了记录,该字段在 DDBB 中声明为 datetime2

【问题讨论】:

  • 2035 = 2019 + 12 + 4。这应该给你一个提示:)。您显示了一个 HSQL 查询,但这不是 Hibernate 为 Sql Server 生成的 SQL 查询。
  • 大声笑,这是一个惊人的效果。 Sql Server 和 Sybase 是唯一(?)使用 + 进行加法和连接的 RDBMS。也许与此有关?
  • 难道没有一个 HSQL“函数”可以将时间戳(日期时间)转换为普通的“DATE”吗?
  • 我对 HSQL/Hibernate 不熟悉,但是否存在一些影响 SQL 查询生成引擎的提供程序兼容性设置?自 2012 年以来,Sql Server 仅具有 CONCAT 语句。也许如果您可以告诉 Hibernate 翻译该最低版本,查询将按预期生成(在 SQL 中使用 CONCAT)。
  • 我认为它有一个 TRUNC 来削减时间部分。但不确定这是否仅适用于 oracle。

标签: sql-server spring hibernate hsqldb concat


【解决方案1】:

为什么要使用concat() 开头?

假设 Hibernate 负责转换非标准的 year()month()day() 函数,那么以下内容应该适用于任何 DBMS

SELECT year(tx.date_), month(tx.date_), day(tx.date_), iss.code 
FROM tx_ tx 
  JOIN issuer_ iss ON tx.id_issuer = iss.id  
GROUP BY year(tx.date_), month(tx.date_), day(tx.date_), iss.code

【讨论】:

  • 对不起,完全是我的错。我没有说出来,但我正在计数以了解发行者和日期的 tx 数量。我现在要编辑我的问题。此外,我使用 concat 的原因是因为我要将该日期存储在另一个表中,并且我不想在后端编写更多逻辑(我认为如果 Hibernate 为我制作 concat 会更有效) .
  • @sunday:即便如此,我认为 concat 是错误的方法。您有三个值,将它们保存在三列中。或者 - 如果可能的话 - 将列转换为正确的 DATE 但我不知道您的混淆层是否可以这样做
【解决方案2】:

感谢Gert Arnold 给我的提示。我只是没有意识到查询的添加就像它们是 MSSQL 中的数字一样。

最后,我设法使其在 4 RDBMS 中首先转换为字符串

SELECT 
 CONCAT(CAST(year(tx.date_) AS string), CAST(month(tx.date_) AS string), CAST(day(tx.date_) AS string)),
 iss.code 
FROM 
 tx_ tx 
JOIN 
 issuer_ iss 
ON 
 tx.id_issuer = iss.id  
GROUP BY 
 CONCAT(year(tx.date_), month(tx.date_), day(tx.date_)), iss.code

我也尝试转换为 TEXT,但它在 MySQL 中引发异常

【讨论】:

    【解决方案3】:

    如何简单地添加它们,而不是使用CONCAT

    (year(tx.date_)*10000 + month(tx.date_)*100 + day(tx.date_)*1) AS datenum
    

    因此,试试这个:

    SELECT 
     CAST((year(tx.date_)*10000 + month(tx.date_)*100 + day(tx.date_)*1) AS string) AS datenum, 
     iss.code 
    FROM tx_ tx 
    JOIN issuer_ iss 
    ON tx.id_issuer = iss.id  
    GROUP BY year(tx.date_), month(tx.date_), day(tx.date_), iss.code
    

    【讨论】:

    • 这可能是最好的与供应商无关的解决方案。
    • 老实说,我有点惊讶具有超过 2 个值的 CONCAT 甚至可以为 Oracle 工作。 Oracle 有更尴尬的东西,这让我认为他们从未雇佣过任何高尔夫编码员。
    • 我看到这个解决方案的问题是,在我的具体情况下,我必须在后端编写更多的逻辑,并且我试图避免它。
    • 那么它必须返回一个字符串吗?哦,这很容易解决。
    猜你喜欢
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    • 2015-06-13
    • 1970-01-01
    • 1970-01-01
    • 2014-07-08
    • 1970-01-01
    相关资源
    最近更新 更多