选择 H2 数据库要求按列分组的案例
Posted
技术标签:
【中文标题】选择 H2 数据库要求按列分组的案例【英文标题】:select case with H2 database asking to group by column 【发布时间】:2020-04-21 10:50:14 【问题描述】:当我使用 HQL 查询我的数据库时,此请求工作正常并返回良好的数据:
select
case
when activityjp0_.status<>'CLOSED'
and (activityjp0_.user_id is null) then 'UNASSIGNED'
else case
when activityjp0_.status<>'CLOSED'
and activityjp0_.deadline<CURRENT_DATE then 'OVERDUE'
else case
when activityjp0_.status='PENDING' then 'IN_PROGRESS'
else activityjp0_.status
end
end
end as col_0_0_,
count(distinct activityjp0_.id) as col_1_0_
from
activities activityjp0_
group by
case
when activityjp0_.status<>'CLOSED'
and (activityjp0_.user_id is null) then 'UNASSIGNED'
else case
when activityjp0_.status<>'CLOSED'
and activityjp0_.deadline<CURRENT_DATE then 'OVERDUE'
else case
when activityjp0_.status='PENDING' then 'IN_PROGRESS'
else activityjp0_.status
end
end
end
当我使用 Criteria API 生成 SAME 请求时,它给出:
select
case
when activityjp0_.status<>?
and (activityjp0_.user_id is null) then 'UNASSIGNED'
else case
when activityjp0_.status<>?
and activityjp0_.deadline<? then 'OVERDUE'
else case
when activityjp0_.status=? then 'IN_PROGRESS'
else activityjp0_.status
end
end
end as col_0_0_,
count(distinct activityjp0_.id) as col_1_0_
from
activities activityjp0_
group by
case
when activityjp0_.status<>?
and (activityjp0_.user_id is null) then 'UNASSIGNED'
else case
when activityjp0_.status<>?
and activityjp0_.deadline<? then 'OVERDUE'
else case
when activityjp0_.status=? then 'IN_PROGRESS'
else activityjp0_.status
end
end
end
但这会导致 JDBC 错误声明:
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Column "ACTIVITYJP0_.USER_ID" must be in the GROUP BY list; SQL statement:
在activityjp0_.status时选择案例?和 (activityjp0_.user_id 为空) 然后是 'UNASSIGNED' 否则当 activityjp0_.status?和activityjp0_.deadline?和 (activityjp0_.user_id 为空) 然后是 'UNASSIGNED' 否则当 activityjp0_.status?和活动jp0_.deadline
如果我在同一个生成的查询中替换变量,并针对我的数据库(在 h2 控制台中)运行它,它运行时没有错误
这怎么可能?
【问题讨论】:
【参考方案1】:你有两个非常相似的表达方式:
case
when activityjp0_.status<>?
and (activityjp0_.user_id is null) then 'UNASSIGNED'
else case
when activityjp0_.status<>?
and activityjp0_.deadline<? then 'OVERDUE'
else case
when activityjp0_.status=? then 'IN_PROGRESS'
else activityjp0_.status
end
end
end
但实际上它们并不相同,因为参数(?
)都是不同的;第一个表达式中有 4 个参数,第二个表达式中有 4 个附加参数。您应该使用group by col_0_0_
而不是group by case … end
,或者您可以在两个表达式中使用相同的索引(?1
、?2
、...)参数。
【讨论】:
这个 sql 是由 hibernate(通过 format_sql=true 属性可见)从我的标准 API 代码生成的,所以我不能使用 ?1 ...我也无法使用生成的别名 col_0_0_也。我用纯 hql & :refDate 参数做了一个测试,它给出了同样的错误 PS:没有参数的纯 HQL(即硬写值)在 H2 中运行良好! 不幸的是,它对 H2 无效(可能对其他一些数据库),Hibernate 的分组查询存在许多已知问题。您的问题看起来像 HHH-11513,但可能是不同的问题。通常的解决方法是使用 Hibernate 的本机查询功能。 感谢澄清,这可能不是有效的 hql 请求。由于我的代码应该跨数据库工作,我不应该使用本机查询。我想我将删除 group by 子句并使用 Streams 将结果分组到内存中。奇怪的是,我们永远无法使用 Hibernate 进行性能优化请求。以上是关于选择 H2 数据库要求按列分组的案例的主要内容,如果未能解决你的问题,请参考以下文章