How to do Group By in grails to order by Count(*) - sql

How do I translate:
SELECT COUNT(*) AS `count`, `a` FROM `b` GROUP BY `a` ORDER BY `a`
into grails or gorm query?

Since grails 1.2 you can create aliases and order by the created alias.
See https://cvs.codehaus.org/browse/GRAILS-3875 and https://cvs.codehaus.org/browse/GRAILS-3655 for more details.
Applied to your own code, the HQL query would be :
def c = b.createCriteria()
def results = c {
projections {
groupProperty("a")
count("a", 'myCount') //Implicit alias is created here !
}
order 'myCount'
}

working in grails 1.2.1
def c = C.createCriteria()
def pl = c.list {
projections {
countDistinct 'id', 'myCount'
groupProperty 'a'
}
order ('myCount', 'desc')
}
the answer is for example
[[10,a3],[2,a1],[1,a2]]

I would try
def c = b.createCriteria()
def results = c {
projections {
groupProperty("a")
rowCount()
}
order("a")
}
Note this is untested.

Related

How do I translate my SQL Query with Having MAX in LINQ?

I'd like to translate this SQL Query in LINQ with EF
SELECT Agts.AgtNum, Agts.AgtLastname, Agts.AgtFirstname, COUNT(Co.CoEnd) FROM [dbo].Agts AS Agts
INNER JOIN [dbo].[Contracts] AS Co ON Agts.AgtNum = Co.AgtNum
GROUP BY Agts.AgtNum, Agts.AgtLastname, Agts.Firstname
HAVING MAX(Co.CoEnd) <= '2020-05-17'
ORDER BY AgtNum asc
I tried that :
public List<AgentToPurge> AgentsToPurge(DateTime datePurge)
{
return (from agent in this.Entities.Agts
join contract in this.Entities.Contracts on agent.AgtNum equals contract.AgtNum
group agent by agent.AgtNum into g
where g.CoEnd <= datePurge
select new AgentToPurge
{
Id = g.Key,
Lastname = g.Key.AgtLastname,
Firstname = g.Key.AgtFirstname,
Contract_Deleted = g.Key.CoEnd.Count()
}).ToList();
}
But the line
where g.CoFin <= datePurge
doesn't work.
I think my "select new" isn't correct either.
Could you help me to solve this ?
Try the following query:
public List<AgentToPurge> AgentsToPurge(DateTime datePurge)
{
return (from agent in this.Entities.Agts
join contract in this.Entities.Contracts on agent.AgtNum equals contract.AgtNum
group contract by new { agent.AgtNum, agent.AgtLastname, agent.AgtFirstname } into g
where g.Max(x => x.CoEnd) <= datePurge
select new AgentToPurge
{
Id = g.Key.AgtNum,
Lastname = g.Key.AgtLastname,
Firstname = g.Key.AgtFirstname,
Contract_Deleted = g.Sum(x => x.CoEnd != null ? 1 : 0)
}).ToList();
}
Note that LINQ query is built from classes and navigation properties and probably you will not need JOIN, if you have properly defined Model.

Aliasing count() for several columns in a group by query in Exposed

I'm trying to create a query like the presented one in the ORM Exposed.
select t.a, t.b, count(*)
from table as t
group by t.a, t.b;
But it seems that .count() supports aliases only for one column, but here I need two columns:
val count = Table.Table.<somehow I need to push both fields a and b here>.count()
Table.Table
.slice(Table.Table.a, Table.Table.b, count)
.selectAll()
.groupBy(Table.Table.a, Table.Table.b)
.map { row ->
Result(
state = row[Table.Table.a],
trigger = row[Table.Table.b],
count = row[count]
)
}
Are you have any ideas on how to do it?
val count = Count(stringLiteral("*"))
This will generate COUNT('*') in your query (which is a valid SQL expression, giving the same result as COUNT(*)).
If you want to get rid of these annoying quotes, you may do the following:
val asterisk = object : Expression<String>() {
override fun toQueryBuilder(queryBuilder: QueryBuilder) {
queryBuilder { +"*" }
}
}
val count = Count(asterisk)

Grails sub query with createCriteria

I have sql query like below
select transf, count(fname) from peak_info where fname in (select peakfile from pe_result where conid = 'GO:0006007' and fdr > 0.05) group by transf;
which I want to implement in grails create criteria. Currently, I am running the SQL query in bracket first and then run an outer query like below:
def test2 = PeResult.createCriteria()
def ptest=test2.list {
eq("conid",conid.toString())
gt("fdr","0.05")
}
def peaknames = ptest.peakfile
def peakinfoFilter = PeakInfo.createCriteria()
def pifilter = peakinfoFilter.list {
'in'("fname", peaknames)

projections
{
groupProperty "transF"
count "fname"
}

}
I was wondering if there are other ways doing this into one query instead of running two queries?
You probably can do something like this. Haven’t executed it but you got the idea. Have a look at subquery section of GORM.
def peakinfoFilter = PeakInfo.createCriteria()
def pifilter = peakinfoFilter.list {
'in' "fname", PeResult.where{
conid == conid.toString()
fdr > "0.05"
}. peakfile
projections
{
groupProperty "transF"
count "fname"
}
}

How to convert this SQL to LINQ or Lambda expression?

here's my sql query below:
Can you guys help me to convert this to a much cleaner one??
SELECT [PurchaseRequestID], [ProjectID],[FullName]
FROM PurchaseRequest
WHERE [PurchaseRequestID] IN
(SELECT [PurchaseRequestID] FROM PurchaseRequestDetail )
AND [PurchaseRequestID] NOT IN
(SELECT [PurchaseRequestID] FROM [PurchaseOrder] )
Though i have already converted this successfuly, i think this is not readable and needs to be rewritten:
var query = from a in db.PurchaseRequests
where
(from b in db.PurchaseRequestDetails
select new
{
b.PurchaseRequestID
}).Contains(new { a.PurchaseRequestID }) &&
!(from c in db.PurchaseOrders
select new
{
c.PurchaseRequestID
}).Contains(new { a.PurchaseRequestID })
select a;
thanks
you really don't need all those anonymous objects. Use the let keyword to introduce temporary variables instead of doing operations on the subqueries directly.
from a in db.PurchaseRequests
let b = from b in db.PurchaseRequestDetails select b.PurchaseRequestID
let c = from c in db.PurchaseOrders select c.PurchaseRequestID
where b.Contains(a.PurchaseRequestID) && !c.contains(a.PurchaseRequestID)
select a;
var query = from a in db.PurchaseRequests
where
db.PurchaseRequestDetails.Any(x => x.PurchaseRequestID == a.PurchaseRequestID) &&
!db.PurchaseOrders.Any(x => x.PurchaseRequestID == a.PurchaseRequestID)
select a;
If you have navigation properties set up, you can write the query like this:
IQueryable<PurchaseRequest> query =
from purchaseRequest in myDataContext.PurchaseRequests
where purchaseRequest.PurchaseRequestDetail.Any()
where !purchaseRequest.PurchaseOrder.Any()
select purchaseRequest;
Or this lambda/method style if you prefer...
IQueryable<PurchaseRequest> query2 = myDataContext.PurchaseRequests
.Where(purchaseRequest => purchaseRequest.PurchaseRequestDetail.Any())
.Where(purchaseRequest => !purchaseRequest.PurchaseOrder.Any());

Grails criteria groupby object

Example grouping by name of the zones:
def result = User.createCriteria().list{
projections {
roles {
zones{
groupProperty("name")
}
}
}
}
but suppose I want to get the "id" or other attributes. the fact is that i want the object on the representing the group and not the string "name".
result.each{ println it.customFuncion() }
"zones" is a hasMany attribute and then i cant group by itself. What should be done, but doesnt works:
def result = User.createCriteria().list{
projections {
roles {
groupProperty("zones")
}
}
}
Is that possible? Thank you guys!
use hql for complex queries:
def result = User.executeQuery("select u.id, zone.name from User as u inner join u.roles as role inner join role.zones as zone group by u.id, zone.name")
Then you can access the result columns as follows:
result.each { row -> row[0] // u.id } // or access via defined column name
Imagine that i do not know your real hasMany collection names.