【问题标题】:Outer join with Scala Slick使用 Scala Slick 进行外部连接
【发布时间】:2012-12-31 20:53:45
【问题描述】:

我有两张桌子,UserUserBusinessPartnerIds

User(id, name, email, whatever)

UserBusinessPartnerIds(userId, bpId)

我正在尝试检索用户和业务合作伙伴 ID 列表。

以下查询工作正常!

database withSession { implicit session: Session =>
      val query = (for {
        (user, userBpid) <- Users leftJoin UserBusinessPartners on (_.id is _.userId)
          if user.email === email &&
             user.password === password &&
             user.active === true &&
             userBpid.dateFrom < today &&
             userBpid.dateTo > today
      } yield (user.id, userBpid.bpId.?))

      val results = query.list

      results.headOption.map( row  => User(row._1, email, password, results.map(_._2).flatten.toSet))
    }

当然,代码的结尾令人发指;但是无所谓。

问题是,我想做一个 OUTER join。因此,如果用户在另一个表中没有与业务伙伴 ID 对应的行,我仍然想获取该用户。

有什么想法吗?

edit - 将问题编辑为实际上是正确的。即使用户没有关联的业务合作伙伴 ID,我仍然想返回用户

【问题讨论】:

    标签: scala slick


    【解决方案1】:

    hmmm,生成的sql是什么样的?应该是左外连接。

    我怀疑问题出在:

    userBpid.dateFrom < today && userBpid.dateTo > today
    

    由于将条件应用于潜在的空值,因此无法返回用户 + 空用户伙伴行;即,当关联的业务伙伴 ID 行不存在时,它们永远不会返回 true。

    作为测试,请执行println(q.sqlStatement) 或查看您的查询日志并手动运行查询,无论是否有上述查询条件。

    编辑 未测试,但试试这个,别名用户业务表,一个内部,一个外部。你可能会得到一个非唯一表别名编译器错误,在我之前尝试使用一些外连接魔法时发生在我身上

    val q = 
      for{
        (u,upo) <- Users leftJoin UserBusinessPartners on (_.id is _.userId)
          if(u.email is email) && (u.password is password) && (u.active is true)
        up <- UserBusinessPartners
          if(u.id is up.userId) && (up.dateFrom < today) && (up.dateTo > today)
        _ <- Query groupBy(u.id)
      } yield (u.id, upo.bpId.?)
    

    【讨论】:

    • 是的,抱歉,应该指出这是问题所在。当可能无法返回时,我们如何“可选地”检查 dateRanges。
    • 只有在用户合作伙伴上的用户外部加入,您不能提供 dateFrom/dateTo 条件。如果你用户内部加入 user-partner1 和外部加入 user-partner2 那么你应该在做生意。
    • 我认为我不太关注,是否愿意编辑您的答案以展示一些甜蜜的业力的例子?
    • 遗憾的是,您提出的解决方案似乎没有奏效;它仍然没有进行外部连接。它至少没有任何编译器问题!
    【解决方案2】:

    您需要在加入之前过滤 UserBusinessPartners 表,这将为您提供没有业务合作伙伴的用户。 类似的东西:

    database withSession { implicit session: Session =>
      userBP = UserBusinessPartners.filter(ubp => ubp.dateFrom < today && ubp.dateTo > today)
      val query = (for {
        (user, userbp) <- Users leftJoin userBP on (_.id is _.userId)
          if user.email === email &&
             user.password === password &&
             user.active === true 
      } yield (user.id, userbp.bpId.?))
    
      val results = query.list
    
      results.headOption.map( row  => User(row._1, email, password, results.map(_._2).flatten.toSet))
    }
    

    过滤器将向您显示仅包含所需业务合作伙伴的表视图,左连接将列出所有用户。

    您的查询失败,原因是:

    userBpid.dateFrom 今天

    由于上述条件,使用 null userBpid 选择的行将被过滤掉。

    【讨论】:

      猜你喜欢
      • 2019-09-02
      • 1970-01-01
      • 1970-01-01
      • 2012-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多