2016-11-15 43 views
1

我有2个表:主要和更新与列名称,ID和部门。 我想先阅读主表,如果部门字段值为空,我可以从更新表读取它。斯卡拉光滑 - 如何从不同的表中获取列值

例如,从下表中,我应该从Update表中获取KING的部门值。

如何实现这个使用scala slick与运行普通sql查询?

主要

+-------+----+------------+ 
+ name | id | department +    
+-------+----+------------+ 
| KING | 10 |   | 
| BLAKE | 30 | SALES  | 
+-------+----+------------+ 

更新

+-------+----+------------+ 
+ name | id | department + 
+-------+----+------------+ 
| KING | 10 | SYSTEMS | 
| BLAKE | 30 | SALES  | 
+-------+----+------------+ 

这里是普通的SQL查询

SELECT 
m.`name`, 
m.`id`, 
if(m.`department`='', u.`department`) as `department` 
FROM `Main` m 
FROM `Update` u ON m.id=u.id 

我有如下到目前为止定义的代码...

case class Main(name: Option[String], 
       id: Option[int], 
       department: Option[String]) 

case class Update(name: Option[String], 
        id: Option[int], 
        department: Option[String]) 

lazy val mainQuery = TableQuery[MainTableDefinition] 
lazy val updateQuery = TableQuery[UpdateTableDefinition] 

class MainTableDefinition(tag: Tag) extends Table[Main](tag, "Main") { 
     def name = column[Option[String]]("name") 
     def id = column[Option[int]]("id") 
     def department = column[Option[String]]("department") 

     override def * = 
     (name, id, department)<> (Main.tupled, Main.unapply) 
} 

class UpdateTableDefinition(tag: Tag) extends Table[Update](tag, "Update") { 
     def name = column[Option[String]]("name") 
     def id = column[Option[int]]("id") 
     def department = column[Option[String]]("department") 

     override def * = 
     (name, id, department)<> (Update.tupled, Update.unapply) 
} 

val query = for { 
    m <- mainQuery 
    u <- updateQuery if m.id === u.id 
} yield (m, u) 

db.run(query.to[List].result) 
+1

您可能想要定义自定义函数'coalesce'(https://www.postgresql.org/docs/9.2/static/functions-conditional.html)并使用它'''val query = for { m < - mainQuery u < - updateQuery如果m.id === u.id department = coalesce(m.department,u.department) } yield(m.id,department)''' –

回答

0

首先你所有的例子:

SELECT 
m.`name`, 
m.`id`, 
if(m.`department`='', u.`department`) as `department` 
FROM `Main` m 
FROM `Update` u ON m.id=u.id 

似乎从两个表中获取值的组合。

DB级解决方案

分贝的水平,也许这样的事情会为你工作:

val query = for { 
    m <- mainQuery 
    u <- updateQuery if m.id === u.id 
} yield { 
    (m.id, m.name, m.department.ifNull(u.department)) 
} 

,我相信是非常接近原始的,所需的查询(但说实话我不完全确定ifNull如何在所有数据库上进行翻译)。

应用级解决方案

在应用层面上,假设你有一个案例类:

case class NameDepartment(name: Option[String], 
        id: Option[int], 
        department: Option[String]) 

(其中顺便说一句你可以在你的解压型两种表定义,因为它们是它可能看起来像这样:

val fetchOperation = (for { 
    m <- mainQuery 
    u <- updateQuery if m.id === u.id 
    } yield (m, u) 
).result.map { results => 
    results.map { case (m, u) => 
     NameDepartment(m.name, m.id, m.department.orElse(u.department)) 
    } 
    } 
+0

谢谢。我会试试这个,让你知道。 –

+0

不能自信地说这个工作。 多次使用地图令人困惑。 –

+0

我假设你只试过第二个版本? 你检查了第一个选项吗?一个表示为:“在数据库级别上,这样的东西可能适合你”< - 它没有多个地图。 还有什么说“不能......说这工作”?你被多个地图弄糊涂了(在第二个例子中),但它满足你的需求或者它不起作用(编译或返回你想要达到的结果)?只是好奇。 编辑:添加部分到我的答案清楚地表明,有两个解决方案。 –