scala - Scala slick:在多列上使用“in”过滤
问题描述
假设我有以下表结构:
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)
);
并且我想生成每个父母的姓名列表。在 slick 中,我可以写如下内容:
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
即使那里有索引,最终也会执行全表扫描以加入(例如,参见H2 的这个错误报告)。一般的问题是查询计划器无法知道分别执行每一侧OR
并将结果重新连接在一起是否更快,或者只是进行全表扫描[2]。
我想生成看起来像这样的 SQL,然后可以按预期使用(主键)索引:
select p.name
from people p, children c
where p.id in (c.parent_id_1, c.parent_id_2)
我的问题是:我怎样才能做到这一点?现有的方法似乎没有提供一种方法:
ColumnExtensionMethods.in
接受Query
作为参数,但我没有一个Query
我有一个数字或Rep[Long]
我的每个 ID 列ColumnExtensionMethods.inSet
用于绑定现有(已知)文字数组,而不是用于连接列集
我希望能够写的是这样的:
for {
parent <- people
child <- children
if parent.id in (child.parent_id_1, child.parent_id_2)
} yield {
p.name
}
但这现在是不可能的。
[1] 我的实际设计比这复杂一点,但归结为同样的问题。
[2] 一些 DBMS确实对简单的情况进行了这种优化,例如Oracle 中的 OR 扩展。
解决方案
事实证明这目前(如 slick 3.2.3)是不可能的,所以我在 github 上提出了一个问题并提交了一个拉取请求来添加这个功能。
推荐阅读
- mysql - 如何从 ASP.NET Core 3.1 MySql.Data.EntityFrameworkCore 调用 MySQL 存储过程
- ruby - 如何将参数传递给mutant-rspec?
- c# - C# 9.0 记录 - 未继承 ToString
- python - Flask 中的请求表为空
- php - PHP提取文档中与搜索词相关的最重要的部分
- c# - 为什么 EF Core 一对多关系集合返回 null?
- html - PayPal 付款后加载微调器
- awk - for 循环将变量传递给 awk cmd
- python - 我可以将 Paraview 的渲染器或交互器添加到我的 PyQt5 应用程序吗?
- python - 平均熊猫数据框中的某些值?