我正在尝试根据案例表达式进行分组。下面的 JOOQ 似乎是正确的做法,并且或多或少产生了我期望的 SQL。从“sakila”数据库(请原谅我的 Kotlin,它必须转义“when”和“as”):
val shared = `when`(ACTOR.LAST_NAME.like("A%"), "A")
.`when`(ACTOR.LAST_NAME.like("B%"), "B")
.otherwise("C")
val r = ctx.select(
count(), shared.`as`("code")
)
.from(ACTOR)
.groupBy(shared)
.fetch()
SQL Server 2017 Express(v14)抱怨:
列“DTB_DEV_SAKILA.dbo.actor.last_name”在选择列表中无效,因为它不包含在聚合函数或 GROUP BY 子句中。
这很令人惊讶,因为确实如此。以下是完整的调试/堆栈跟踪(我已将其半格式化以便于阅读):
Exception in thread "main" org.jooq.exception.DataAccessException: SQL [
select count(*),
case when [DTB_DEV_SAKILA].[dbo].[actor].[last_name] like ? then ?
when [DTB_DEV_SAKILA].[dbo].[actor].[last_name] like ? then ?
else ? end [code]
from [DTB_DEV_SAKILA].[dbo].[actor]
group by case when [DTB_DEV_SAKILA].[dbo].[actor].[last_name] like ? then ?
when [DTB_DEV_SAKILA].[dbo].[actor].[last_name] like ? then ? else ? end
]; Column 'DTB_DEV_SAKILA.dbo.actor.last_name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
令人恼火的是,如果我剪切/粘贴查询(由堆栈跟踪吐出)并用实际值替换占位符/准备好的语句“?”,SSMS 就可以很好地执行它。
select
count(*),
case
when [DTB_DEV_SAKILA].[dbo].[actor].[last_name] like 'A%'
then 'A'
when [DTB_DEV_SAKILA].[dbo].[actor].[last_name] like 'B%'
then 'B'
else 'C'
end as code
from
[DTB_DEV_SAKILA].[dbo].[actor]
group by
case
when [DTB_DEV_SAKILA].[dbo].[actor].[last_name] like 'A%' then 'A'
when [DTB_DEV_SAKILA].[dbo].[actor].[last_name] like 'B%' then 'B'
else 'C'
end as code
笔记:
- 如果我使用 JOOQ 的
inline()
函数来摆脱准备好的语句“?”(呃,绑定变量),它可以正常工作; - 使用 IIF 而不是 CASE WHE N ...没有任何喘息的机会,它抱怨同样的事情。
但是这段代码(我猜没有绑定变量,只是列引用)运行得很好:
val shared = length(ACTOR.LAST_NAME)
val r = ctx.select(
count(), shared.`as`("voluminousness")
)
.from(ACTOR)
.groupBy(shared)
.fetch()
因此,问题在于,在尝试编译时,根据 case 语句进行分组的一些联系PreparedStatement
。
这似乎更像是 JDBC / SQL Server 问题,而不是 JOOQ 问题。但是 JOOQ 用户通常会采用与此处不同的方法吗?有解决方法吗?其他数据库是否也有这样的分组限制CASE
?
JOOQ 3.19.10、MS JDBC 12.8.1.jre11、SQL Server 2017(v14.0.2065)