27

I want to force slick to create queries like

select max(price) from coffees where ... 

But slick's documentation doesn't help

val q = Coffees.map(_.price) //this is query Query[Coffees.type, ...]
val q1 = q.min // this is Column[Option[Double]]
val q2 = q.max
val q3 = q.sum
val q4 = q.avg 

Because those q1-q4 aren't queries, I can't get the results but can use them inside other queries.

This statement

for {
  coffee <- Coffees
} yield coffee.price.max

generates right query but is deprecated (generates warning: " method max in class ColumnExtensionMethods is deprecated: Use Query.max instead"). How to generate such query without warnings?

Another issue is to aggregate with group by:

"select name, max(price) from coffees group by name"

Tried to solve it with

for {
  coffee <- Coffees
} yield (coffee.name, coffee.price.max)).groupBy(x => x._1)

which generates

select x2.x3, x2.x3, x2.x4 from (select x5."COF_NAME" as x3, max(x5."PRICE") as x4 from "coffees" x5) x2 group by x2.x3

which causes obvious db error

column "x5.COF_NAME" must appear in the GROUP BY clause or be used in an aggregate function

How to generate such query?

virtualeyes
  • 11,147
  • 6
  • 56
  • 91
Jeriho
  • 7,129
  • 9
  • 41
  • 57

1 Answers1

31

As far as I can tell is the first one simply

Query(Coffees.map(_.price).max).first

And the second one

val maxQuery = Coffees
  .groupBy { _.name }
  .map { case (name, c) =>
    name -> c.map(_.price).max
  }

maxQuery.list

or

val maxQuery = for {
  (name, c) <- Coffees groupBy (_.name)
} yield name -> c.map(_.price).max

maxQuery.list
EECOLOR
  • 11,184
  • 3
  • 41
  • 75
  • 4
    instead of `.list.head` you can do `.first`, IIRC –  Mar 04 '13 at 10:41
  • Thanks, I changed it in the answer – EECOLOR Mar 04 '13 at 11:43
  • Thanks, both examples work, second generates optimal query "select x2."COF_NAME", max(x2."PRICE") from "coffees" x2 group by x2."COF_NAME"", but the first one generates "select x2.x3 from (select max(x4.x5) as x3 from (select x6."PRICE" as x5 from "coffees" x6) x4) x2" - query with 2 subqueries instead of simple "select max(x2."PRICE") from "coffees" x2" that is generated by deprecated api. It seems that slick developers deprecated this api too early. – Jeriho Mar 04 '13 at 20:40
  • 1
    Note: in Slick2 run method is needed instead of list/first, see http://stackoverflow.com/questions/23830960/slick-2-aggregation-how-to-get-a-scalar-result/23831610?noredirect=1#23831610 – Suma May 23 '14 at 14:31