2016-11-15 15 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

我假設你只試過第二個版本? 你檢查了第一個選項嗎?一個表示爲:「在數據庫級別上,這樣的東西可能適合你」< - 它沒有多個地圖。 還有什麼說「不能......說這工作」?你被多個地圖弄糊塗了(在第二個例子中),但它滿足你的需求或者它不起作用(編譯或返回你想要達到的結果)?只是好奇。 編輯:添加部分到我的答案清楚地表明,有兩個解決方案。 –