我正在尝试使用Jooq进行以下操作,并且不能为我的生活找到如何正确地做到这一点:
select name, id in (
select capability_id
from a.capabilities_users
where user_id = ?)
from a.capabilities;
基本上我想获得所有项目(功能)并知道每个项目是否适用于特定用户。似乎所有条件类型操作符(如大于或在中)只能在where而不是select中使用。我想不出怎么表达这个。
最糟糕的情况是,我可以选择计数,然后在Java中执行布尔逻辑,但我希望使用fetchMap。
答案 0 :(得分:4)
根据您的数据库和架构元数据,LEFT JOIN
可能是比预测中的谓词更好的选择。您当然应该在执行计划中验证这一点。
LEFT JOIN
:-- NVL2 is Oracle syntax.
-- jOOQ will emulate NVL2 using CASE, if it's not available in your database
SELECT c.name, NVL2(cu.capability_id, 1, 0)
FROM a.capabilities c
LEFT OUTER JOIN a.capabilities_users cu
ON (c.id = cu.capability_id
AND cu.user_id = ?)
当然,上述假设cu(user_id, capability_id)
存在不合理的约束。然后这将转化为jOOQ:
Capabilities c = CAPABILITIES.as("c");
CapabilitiesUsers cu = CAPABILITIES_USERS.as("cu");
Field<String> key = c.NAME.as("key");
Field<Boolean> value = nvl2(
CAPABILITIES_USER.CAPABILITY_ID, true, false
).as("value");
Map<String, Boolean> map =
DSL.using(configuration)
.select(key, value)
.from(c)
.leftOuterJoin(cu)
.on(c.ID.eq(cu.CAPABILITY_ID))
.and(cu.USER_ID.eq(...))
.fetchMap(key, value);
如果你真的更喜欢投影中的谓词,你可以试试DSL.field(Condition)
,这恰好就是这样:
Field<String> key = CAPABILITIES.NAME.as("key");
Field<Boolean> value = field(
CAPABILITIES.ID.in(
select(CAPABILITY_ID)
.from(CAPABILITIES_USERS)
.where(CAPABILITIES_USERS.USER_ID.eq(...))
)
).as("value");
Map<String, Boolean> map =
DSL.using(configuration)
.select(key, value)
.from(CAPABILITIES)
.fetchMap(key, value);
请注意,如果您使用的是符合标准的数据库,该数据库不允许将谓词视为列,DSL.field(Condition)
将为您呈现等效的CASE
语句。