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

问题描述 投票:3回答:1

假设我有以下表结构:

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)
);

并且我想生成每个父母的姓名列表。在光滑的我可以写一些像:

for {
  parent <- people
  child  <- children if {
    parent.id === child.parent_id_1 ||
    parent.id === child.parent_id_2
  }
} yield {
  parent.name
}

这会生成预期的SQL:

select p.name
from people p, children c
where p.id = c.parent_id_1 or p.id = c.parent_id_2

然而,这不是最佳的:表达式的OR部分可能会导致某些DBMS中的性能极其缓慢,最终进行全表扫描以加入p.id,即使那里有索引(例如参见this bug report for H2)。一般的问题是查询规划器无法知道分别执行OR的每一面并将结果重新连接起来更快,或者只是进行全表扫描[2]。

我想生成看起来像这样的SQL,然后可以按预期使用(主键)索引:

select p.name
from people p, children c
where p.id in (c.parent_id_1, c.parent_id_2)

我的问题是:我怎么能在浮油中做到这一点?现有方法似乎没有提供方法:

我想能写的是这样的:

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

但现在不可能。

[1]我的实际设计比这更复杂,但归结为同样的问题。

[2]一些DBMS确实对简单情况进行了这种优化,例如: OR-expansion in Oracle

scala slick slick-3.0
1个回答
0
投票

事实证明这不是当前(如在光滑的3.2.3)可能,所以我有raised an issue on github并提交了一个拉取请求来添加此功能。

© www.soinside.com 2019 - 2024. All rights reserved.