我正在尝试在scala Active record中编写特定的查询。但是它始终不返回任何内容。我已经阅读了github页面上的wiki,但是其中没有包含很多信息。我要写的查询是
SELECT e.name, e.id, COUNT(pt.pass_id) as pass_count, e.start_date, e.total_passes_to_offer
FROM events e inner join passes p on e.id = p.event_id inner join pass_tickets pt on p.id = pt.pass_id where e.partner_id = 198 group by e.name, e.id
我尝试过的是
Event.joins[Pass, PassTicket](
(event, pass, passTicket) => (event.id === pass.eventId, pass.id === passTicket.passId)
).where(
(event, _, _) => event.partnerId === partnerId
).select(
(event, pass, _) => (event.name, event.id, PassTicket.where(_.passId === pass.id).count, event.startDate, event.totalPassesToOffer)
).groupBy( data => data._2)
但是首先,返回类型成为一个映射,而不是一个列表。第二,执行时,即使数据存在也不返回任何内容。直接对数据库运行SQL查询时,将返回预期结果。
答案 0 :(得分:4)
scala-activerecord
dsl是基于squeryl
的,因此,当找出一个复杂的查询时,我们可以降至squeryl级别,并使用其statement
工具来漂亮地打印SQL语句。这样,我们可以迭代tsl每周一次,直到获得所需的SQL语句。例如,假设我们具有以下架构:
object Tables extends ActiveRecordTables {
val persons = table[Person]
val tickets = table[Ticket]
}
case class Person(name: String, email: String, age: Int) extends ActiveRecord
case class Ticket(price: Float, priority: Boolean) extends ActiveRecord {
lazy val person = belongsTo[Person]
}
object Person extends ActiveRecordCompanion[Person]
object Ticket extends ActiveRecordCompanion[Ticket]
,我们将使用squeryl dsl定义以下查询
val query =
dsl.join(Person.toQuery, Ticket.toQuery)((person, ticket) =>
groupBy(person.name, person.age)
compute(count(ticket.id))
on(person.id === ticket.id)
)
然后我们可以使用
漂亮地打印语句println(Person.inTransaction(query.statement))
输出实际的SQL语句
Select
q1.people6_name as g0,
q1.people6_age as g1,
count(q7.tickets11_id) as c0
From
(Select
people6.name as people6_name,
people6.email as people6_email,
people6.age as people6_age,
people6.id as people6_id
From
people people6
) q1
inner join (Select
tickets11.priority as tickets11_priority,
tickets11.price as tickets11_price,
tickets11.id as tickets11_id
From
tickets tickets11
) as q7 on (q1.people6_id = q7.tickets11_id)
Group By
q1.people6_name,
q1.people6_age
一旦我们在squeryl中找到了正确的dsl,那么我们至少知道这是可能的,然后我们可以尝试将其也写在scala-activerecord中。这种方法的潜在优势在于,似乎可以轻松获取更多文档。注意它在Group and Aggregate Queries上的内容,对于scala-activerecord也应间接适用:
Squeryl与SQL稍有不同,因为集合函数不是 在选择范围内允许。相反,它们在“计算”中声明 子句实际上是变相的选择,因为它的参数结尾 在生成的SQL的select子句中。这样做的动机 设计的选择是使编写无效的Select更加困难 语句,因为 DSL强制使用“ compute”子句来替换 选择或跟随组。
根据我的理解,这意味着我们不应该在PassTicket.where(_.passId === pass.id).count
子句中写select
。
关于groupBy
返回Map
,我们可以在其上调用values.toList
以取回列表,例如,说我们有
Person("Picard", "picard@starfleet.org", 34).save
Person("Data", "data@starfleet.org", 40).save
Person("Geordi", "geordi@starfleet.org", 40).save
然后println(Person.groupBy(person => person.age).values.toList)
应该给予
List(
List(Person(Data,data@starfleet.org,40), Person(Geordi,geordi@starfleet.org,40)),
List(Person(Picard,picard@starfleet.org,34))
)