I have a table T with columns A & C, from which I would like to retrieve an average count like so:
select avg(AC) as AV
from
(
select A, count(1) as AC
from T
where C = 1
group by A
)
How do I accomplish this in GORM? GRAILS version 2.2.0 I tried following the documentation but there are no good examples. I couldn't even get the subquery to work :(
Update
I was able to get the count portion to work. Still now sure how to get the average since I don't know how to select from a query.
def tc = T.createCriteria()
def tCounts = tc.buildCriteria {
and {
eq 'C', 1
}
projections {
groupProperty 'A'
rowCount('AC')
}
}
Here is done in HQL. Tested in a grails console with one of my domains:
T.executeQuery("""
select avg(count(*))
from T t
where t.c = 1
group by t.a
""")
UPDATE
Lately it was found that in-memory database was restricting to use avg()
on count()
. After numerous cross-examination, it was found that with Oracle db actually the below HQL can yield appropriate result and would eradicate the complexity of fetching the rows from db and then calculating the average in Groovy:
T.executeQuery("select avg(count(t)) from Team as t where t.c = 1 group by t.a")
The problem I was facing with in-memory db is showcased as a sample.
INIT
On my first look at the query I thought it can be achieved by using DetachedCriteria
but avg
projection can only be applied on domain properties but cannot be applied on count()
. Same goes with HQL.
You can use combination of withCriteria
and groovy collect
to get the average of count of A as:
def countOfA = T.withCriteria{
eq 'c', 1
projections{
count 'a'
groupProperty 'a'
}
}?.collect{it?.first()}
def averageCount = countOfA ? (countOfA.sum() / countOfA.size()) : 0