4

我正在尝试对 Jooq 执行以下操作,但我一生都无法弄清楚如何正确地做到这一点:

select name, id in (
  select capability_id 
   from a.capabilities_users 
   where user_id = ?) 
from a.capabilities;

基本上我想获取所有项目(功能)并知道每个项目是否适用于特定用户。似乎所有条件类型运算符(如大于或 in)只能用于 where 而不能用于 select。我想不出还有什么办法来表达这一点。

最坏的情况,我可以做一个选择计数,然后在 Java 中做布尔逻辑,但我希望使用 fetchMap。

4

1 回答 1

5

根据您的数据库和模式元数据,aLEFT 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 = ?)

当然,上面假设存在一个 unqiue 约束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语句。

于 2013-09-14T06:54:27.463 回答