@semicolon:
chcę wyprowadzić z pozostałych tabelek dodatkową kolumnę pod wspólnym aliasem
Aliasów na potrzeby zapytania nie ma sensu definiować w Slicku, bo operuje się np na krotkach (i Slick sam tworzy swoje aliasy przy tworzeniu zapytania). Są sobie oficjalne testy https://github.com/slick/slick/blob/6e20f96bba0d84e9bb755b489b0bd73d422ca039/slick-testkit/src/main/scala/com/typesafe/slick/testkit/tests/UnionTest.scala gdzie pokazane jest kilka scenariuszy, np union między dwiema tabelami o różnych kolumnach:
class Managers(tag: Tag) extends Table[(Int, String, String)](tag, "managers") {
def id = column[Int]("id")
def name = column[String]("name")
def department = column[String]("department")
def * = (id, name, department)
}
lazy val managers = TableQuery[Managers]
class Employees(tag: Tag) extends Table[(Int, String, Int)](tag, "employees") {
def id = column[Int]("id")
def name = column[String]("name2")
def manager = column[Int]("manager")
def * = (id, name, manager)
// A convenience method for selecting employees by department
def departmentIs(dept: String) = manager in managers.filter(_.department === dept).map(_.id)
}
lazy val employees = TableQuery[Employees]
def managersQuery = for(m <- managers filter { _.department === "IT" }) yield (m.id, m.name)
def employeesQuery = for(e <- employees filter { _.departmentIs("IT") }) yield (e.id, e.name)
val managersData = Seq(
(1, "Peter", "HR"),
(2, "Amy", "IT"),
(3, "Steve", "IT")
)
val employeesData = Seq(
(4, "Jennifer", 1),
(5, "Tom", 1),
(6, "Leonard", 2),
(7, "Ben", 2),
(8, "Greg", 3)
)
def testBasicUnions = {
val q1 = managersQuery
val q2 = employeesQuery
val q3 = (q1 union q2).sortBy(_._2.asc)
val q4 = managers.map(_.id)
val q4b = q4 union q4
val q4c = q4 union q4 union q4
val q5 = managers.map(m => (m.id, 0)) union employees.map(e => (e.id, e.id))
(for {
_ <- (managers.schema ++ employees.schema).create
_ <- managers ++= managersData
_ <- employees ++= employeesData
_ <- mark("q1", q1.result).map(r => r.toSet shouldBe Set((2,"Amy"), (3,"Steve")))
_ <- mark("q2", q2.result).map(r => r.toSet shouldBe Set((7,"Ben"), (8,"Greg"), (6,"Leonard")))
_ <- mark("q3", q3.result).map(_ shouldBe List((2,"Amy"), (7,"Ben"), (8,"Greg"), (6,"Leonard"), (3,"Steve")))
_ <- mark("q4b", q4b.result).map(r => r.toSet shouldBe Set(1, 2, 3))
_ <- mark("q4c", q4c.result).map(r => r.toSet shouldBe Set(1, 2, 3))
_ <- mark("q5", q5.result).map(r => r.toSet shouldBe Set((7,7), (6,6), (2,0), (4,4), (3,0), (8,8), (5,5), (1,0)))
} yield ()) andFinally (managers.schema ++ employees.schema).drop
}
Jak widać można sobie filtrować, mapować, robić unię i sortować:
def managersQuery = for(m <- managers filter { _.department === "IT" }) yield (m.id, m.name)
def employeesQuery = for(e <- employees filter { _.departmentIs("IT") }) yield (e.id, e.name)
val q1 = managersQuery
val q2 = employeesQuery
val q3 = (q1 union q2).sortBy(_._2.asc)
PS: gdybym miał pisać coś od zera to pewnie wypróbowałbym Quill. Slick miejscami wygląda na przekombinowanego i trochę walczyłem z typami jak chcialem tworzyć abstrakcje (np podmiana JdbcProfiles, abstrakcje na tworzenie, czyszczenie, usuwanie tabel, itd już nawet nie pamiętam, bo dawno nie kombinowałem nic w Slicku).