【问题标题】:Slick outer join with multiple tables具有多个表的光滑外部联接
【发布时间】:2014-04-07 06:52:02
【问题描述】:

在两个表之间进行外连接很容易:

tblA.leftJoin(tblB).on(_.aId === _.bId)

但是当在 5 个表之间进行连接时,它很快就会变得笨拙:

tblA.leftJoin(tblB).on(_.aId === _.bId).
    leftJoin(tblC).on(_._1.aId === _.cId).
    leftJoin(tblD).on(_._1._1.aId === _.dId).
    leftJoin(tblE).on(_._1._1._1.aId === _.eId)

元组访问器变得有点混乱,尤其是当它们不都访问第一个表时。

有没有更好的办法?

内连接在语义上等同于带有过滤器的flatMap这一事实解决了内连接的这个问题:

for {
    a <- tblA
    b <- tblB if a.aId === b.bId
    c <- tblC if a.aId === c.cId
    d <- tblD if a.aId === d.dId
    e <- tblE if a.aId === e.eId
} yield ???

外连接有类似优雅的语法吗?

【问题讨论】:

    标签: scala slick


    【解决方案1】:

    这个怎么样?

    tblA.leftJoin(tblB).leftJoin(tblC).leftJoin(tblD).leftJoin(tblE).on{
      case ((((a,b),c),d),e) =>
        a.aId === b.bId &&
        a.aId === c.cId &&
        a.aId === d.dId &&
        a.aId === e.eId
    }
    

    目前无法生成最好的 SQL,但我们希望尽快改进。

    产生 HLists 的左连接应该允许甚至使模式匹配更好,但可能被阻止:https://github.com/slick/slick/issues/728

    【讨论】:

    • 我尝试了这种方法,并且 slick 生成的 SQL 查询包含一些语法错误,MySQL 无法运行它。也有人说,通过其他方式执行多个左连接生成的查询在 MySQL 上执行起来确实很慢。这些问题有解决方案吗?
    • 如果它产生了无效的 SQL,请确保您使用 Slick 2.0.1,如果仍然如此,请报告一个带有重现步骤的错误和它产生的无效 SQL。我们知道这个问题,MySQL 优化器似乎对子选择非常糟糕,而 Slick 目前在某些情况下会不必要地生成子选择。你试过 MySQL 5.6 吗?优化器得到了显着改进。此外,Slick 可能会在某个时候在该领域有所改进。这是一种用优化的 SQL 手动替换非优化 SQL 的模式:gist.github.com/cvogt/8054159 不过它需要适应 Slick 2。
    • 我使用的是 Slick 2.0.1,而我们公司使用的是 MySQL 5.5,所以我没有在 5.6 上试用。我将尝试在我们的代码之外重现失败的查询,如果我成功了,我将打开一个问题。还是谢谢你的指点!
    • 使用 Slick 2.1.0 我也得到了无效的 SQL(引用的列不存在)。 (“不会产生最好的 SQL”:涉及派生表,如果手动编写 A LEFT JOIN B LEFT JOIN C,您可能不会这样做。)
    • 尝试 3.0。 Slick 3.1 将改进生成的 SQL 的结构
    猜你喜欢
    • 2019-05-19
    • 2013-07-06
    • 2020-10-25
    • 2015-01-05
    • 1970-01-01
    • 2013-09-03
    • 1970-01-01
    • 2014-08-21
    • 1970-01-01
    相关资源
    最近更新 更多