加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 为什么这两个Slick查询不相同?

发布时间:2020-12-16 18:36:47 所属栏目:安全 来源:网络整理
导读:作为 trying to make a Slick query more readable的结果,我有这个查询构造函数,它的工作原理 val q = Users.filter(_.id === userId) join People on { case (u,p) = u.personId === p.id} joinLeft Addresses on { case ((u,p),a) = p.addressId === a.id}
作为 trying to make a Slick query more readable的结果,我有这个查询构造函数,它的工作原理

val q = Users.filter(_.id === userId) join People on {
  case (u,p) => u.personId === p.id
} joinLeft Addresses on {
  case ((u,p),a) => p.addressId === a.id
} joinLeft Businesses on {
  case (((u,a),b) => p.businessId === b.id
} joinLeft Addresses on {
  case ((((u,b),ba) => b.flatMap(_.addressId) === ba.id
} map {
  case ((((u,ba) => (p,a,b,ba)
}

我认为这个是等价的,但不起作用:

val q = Users.filter(_.id === userId) join People joinLeft Addresses joinLeft Businesses joinLeft Addresses on {
  case ((((u,ba) =>
    u.personId === p.id &&
    p.addressId === a.flatMap(_.id) &&
    p.businessId === b.flatMap(_.id) &&
    b.flatMap(_.addressId) === ba.id
} map {
  case ((((u,ba)
}

第二个似乎是返回一个包含超过目标的配置文件列表.

他们为什么不一样?

“等效”SQL(IE构建的目标)是:

select p.*,a1.*,b.*,a2.* from Users u 
innerJoin People p on (u.personId == p.id) 
leftJoin Addresses a1 on (p.addressId == a1.id) 
leftJoin Businesses b on (p.businessId == b.id) 
leftJoin Addresses a2 on ( b.addressId == a2.id)

解决方法

这里的问题是,slick uses a LiteralNode(true) as the default join condition.所以第二个查询将产生如下所示的内容:

select p.*,a2.*
     from Users u 
     join People p on 1 = 1
left join Addresses a1 on 1 = 1
left join Businesses b on 1 = 1 
left join Addresses a2 on u.personId = p.id
                      and p.addressId = a1.id
                      and p.businessId = b.id
                      and b.addressId = a2.id

如您所见,预期每个连接表的连接条件的所有条件实际上是最后一个连接的连接条件的一部分.

要了解这将如何影响最终结果,让我们简化问题如下:

create temporary table A (id int primary key);

insert into A values (1),(2);

   select a1.id,a2.id,a3.id
     from A a1
     join A a2 on 1 = 1
left join A a3 on a1.id = a2.id
              and a2.id = a3.id;

在第一次连接时,a1和a2由一个始终为true的条件连接,从而产生以下临时结果:

(1,1)
(1,2)
(2,1)
(2,2)

现在让我们考虑第二次加入.我们将a1.id = a2.id作为连接条件的一部分,但请记住连接条件用于决定如何从表a3中检索行,而不是过滤第一个连接的中间结果.我们在这里进行左连接,因此即使不满足连接条件,也会生成额外的a3行NULL.最终结果将是:

(1,1,2,NULL)
(2,2)

因此,当前一个左连接表的列为NULL时,您可能会看到更多意外结果.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读