Scala slick:在多列上使用“in”进行过滤

Ash*_*cer 5 scala slick slick-3.0

假设我有以下表结构:

create table PEOPLE (
    ID integer not null primary key,
    NAME varchar(100) not null
);

create table CHILDREN (
    ID integer not null primary key,
    PARENT_ID_1 integer not null references PERSON (id),
    PARENT_ID_2 integer not null references PERSON (id)
);
Run Code Online (Sandbox Code Playgroud)

我想生成每个父母的姓名列表。在光滑的我可以写这样的东西:

for {
  parent <- people
  child  <- children if {
    parent.id === child.parent_id_1 ||
    parent.id === child.parent_id_2
  }
} yield {
  parent.name
}
Run Code Online (Sandbox Code Playgroud)

这会生成预期的 SQL:

select p.name
from people p, children c
where p.id = c.parent_id_1 or p.id = c.parent_id_2
Run Code Online (Sandbox Code Playgroud)

然而,这并不是最优的:表达式的一部分可能会导致某些 DBMS 的性能极其缓慢,即使那里有索引,OR最终也会进行全表扫描来连接(例如,请参阅H2 的错误报告)。一般问题是查询规划器无法知道单独执行每一侧并将结果连接在一起是否更快,或者简单地进行全表扫描 [2]。p.idOR

我想生成如下所示的 SQL,然后可以按预期使用(主键)索引:

select p.name
from people p, children c
where p.id in (c.parent_id_1, c.parent_id_2)
Run Code Online (Sandbox Code Playgroud)

我的问题是:我怎样才能做到这一点?现有的方法似乎没有提供办法:

我希望能够写的是这样的:

for {
  parent <- people
  child  <- children
  if parent.id in (child.parent_id_1, child.parent_id_2)
} yield {
  p.name
}
Run Code Online (Sandbox Code Playgroud)

但现在这是不可能的。

[1] 我的实际设计比这复杂一点,但归根结底是同样的问题。

[2] 一些 DBMS确实对简单情况进行了这种优化,例如Oracle 中的 OR 扩展。

Ash*_*cer 0

事实证明,这目前是不可能的(在 slick 3.2.3 中),所以我在 github 上提出了一个问题并提交了一个 Pull 请求来添加此功能。