how to use subquery in order by with case in nhibernate? - sql

I need to fetch result from DB table using nhibernate with QueryOver for below sql query. The SQL request is like this:
SELECT Id, Name, Address,phone,ispassed
FROM employee WHERE ispassed = 1
ORDER BY
(CASE WHEN id in (select empId from salary where empId in (2,45,65) and Type=5) THEN 0 ELSE 1 END) asc,
Name desc
I am stuck in Order by. So, please give an example to construct nhibernate query for
ORDER BY
(CASE WHEN id in (select empId from salary where empId in (2,45,65)
and Type=5) THEN 0 ELSE 1 END) asc
I have sub query as :
var subquery = QueryOver.Of<salary>()
.Where(x => x.Type == 5 && x.empId.IsIn(2,65,45))
.SelectList(list => list
.Select(Projections.Distinct(Projections.Property<salary>(x => x.empId))));
and when I am adding subquery in main query as :
query.OrderBy(Projections.Conditional(
Restrictions.In(Projections.SubQuery(subquery)),
Projections.Constant(0),
Projections.Constant(1))).Asc();
It is showing error as "The best overloaded method match for 'NHibernate.Criterion.Projections.SubQuery(NHibernate.Criterion.DetachedCriteria)' has some invalid arguments."

I hope that's what you want:
Employee employeeAlias = null;
var subquery = QueryOver.Of<salary>()
.Where(x => x.Type == 5 && x.empId.IsIn(2,65,45))
.And(x => x.empId == employeeAlias.Id)
.Select(x => x.empId);
var query = session.QueryOver(() => alias)
.Where(x => x.IsPassed)
.OrderBy(Projections.Conditional(
Subqueries.Exists(subquery.DetachedCriteria),
Projections.Constant(0),
Projections.Constant(1))
).Asc
.ThenBy(x => x.Name).Desc
//.Select
//.List
;

Related

Sum of a subquery in NHibernate

I am using NHibernate 3.3.1.4000.
Here's what I would like to achieve:
SELECT sum(tr_time)
FROM (SELECT seg.translation_time as tr_time
FROM "TRANSLATION" seg
WHERE seg.translation_time > 0 and seg.fk_id_language = 34
ORDER BY seg.translation_time ASC
LIMIT 1000) as subquery
The easiest way, using LINQ to NHibernate, fails with a NotSupportedException:
session.Query<Translation>()
.Where(s => s.Language == language && s.TranslationTime > 0)
.OrderBy(s => s.TranslationTime)
.Take(1000)
.Select(s => s.TranslationTime)
.Sum(s => s);
I was able to produce this SQL:
SELECT sum(this_.translation_time) as y0_
FROM "TRANSLATION" this_
WHERE this_.id in (SELECT this_0_.id as y0_
FROM "TRANSLATION" this_0_
WHERE this_0_.fk_id_language = 34
and this_0_.translation_time > 0
ORDER BY this_0_.translation_time asc
LIMIT 1000)
with the following query:
session.QueryOver<Translation>(() => translationAlias)
.WithSubquery.WhereProperty(s => s.Id)
.In(QueryOver.Of<Translation>(() => translationSubAlias)
.Where(s => s.Language == language)
.Where(s => s.TranslationTime > 0)
.Select(s => s.Id)
.OrderBy(s => s.TranslationTime).Asc
.Take(1000))
.Select(Projections.ProjectionList()
.Add(Projections.Sum(Projections.Property(() => translationAlias.TranslationTime))))
.FutureValue<Int32>();
However, that's obviously not ideal as the WHERE ... IN clause is not necessary.
I tried things like
session.QueryOver<Translation>(() => translationAlias)
.Select(Projections.ProjectionList()
.Add(Projections.Sum(
Projections.Alias(
Projections.SubQuery(
QueryOver.Of<Translation>(() => translationSubAlias)
.Where(() => translationSubAlias.Language == language)
.Where(() => translationSubAlias2.TranslationTime > 0)
.Select(Projections.Property("TranslationTime"))), "tr_time"))))
.FutureValue<Int32>()
but it generates this SQL:
SELECT sum((SELECT this_0_.translation_time as y0_
FROM "TRANSLATION" this_0_
WHERE this_0_.fk_id_language = 34 and this_0_.translation_time > 0)) as y0_
FROM "TRANSLATION" this_
which the database server rejects with the following error message: more than one row returned by a subquery used as an expression
I don't really care which method I would eventually use (LINQ, QueryOver, Criteria API) as long as it allows future queries.
Any chance it is not returning any values? If that is the case, you need to make TranslationTime nullable:
session.Query<Translation>()
.Where(s => s.Language == language && s.TranslationTime > 0)
.OrderBy(s => s.TranslationTime)
.Take(1000)
.Select(s => s.TranslationTime)
.Sum(s => (int?) s);
Notice the "int?" cast, assuming TranslationTime is of type int.

Nhibernate QueryOver - .SelectCount() with predicate

I need to select count of row with a condition:
Query to collect the full count:
var searchs = searchQuery.SelectList
(list => list
.SelectGroup(order => order.Id).WithAlias(() => groupResult.GlobalId)
.SelectCount(() => _transaction.ReturnStatus).WithAlias(() => groupResult.DeclineCount)
)
I need count of transactions that equals 201. Something like this:
.SelectCount(() => _transaction.ReturnStatus == 201).WithAlias(() => groupResult.DeclineCount) //runtime error
Thanks in advance!
PS:
Original SQL Query:
SELECT TOP 100
globalOrd.ID AS GlobalId ,
SUM(CASE WHEN transact.returnStatus = 201 THEN 1
ELSE 0
END) AS DeclineCount
FROM Orders.Global globalOrd
INNER JOIN Orders.TransactionDetail transactDet ON globalOrd.ID = transactDet.DetailID
INNER JOIN Orders.[Transaction] transact ON transactDet.TransactionID = transact.ID
GROUP BY globalOrd.ID
If you don't need the total count in the same query you can simply add in the restriction before the SelectList:
var searchs = searchQuery.SelectList
(list => list
.Where(() => _transaction.ReturnStatus == 201)
.SelectGroup(order => order.Id).WithAlias(() => groupResult.GlobalId)
.SelectCount(() => _transaction.ReturnStatus).WithAlias(() => groupResult.DeclineCount)
)
If however, you want both the total and the restricted count, you would have to use a SqlProjection for the latter doing something like:
SUM(CASE {alias}.ReturnStatus WHEN 201 THEN 1 ELSE 0 END)

nhibernate QueryOver - complex subselect

How can I write this query with QueryOver.
select * from User usr where exists (select ord.ID from Order ord where ord.UserID = usr.ID)
I know we can write subqueries with QueryOver like ..WithSubSelect.WhereProperty(x=>x.ID == subquery.as<int>()). But I want to use field of the main query in the subquery in order to use it in where clause.
Is this possible ?
thank you for your helps
User userAlias = null;
var subquery = QueryOver.Of<Order>()
.Where(o => o.User == userAlias)
// or
.Where(o => o.User.Id == userAlias.Id)
var usersWithOrders = session.QueryOver(() => userAlias)
.WithSubqueries.WhereExists(subquery)
.List();

Convert SQL to LINQ JOIN/GROUP BY/COUNT/DISTINCT

I got a rather tough query to convert from SQL to LINQ-to-Entities.
Here's my SQL code:
select c_id
from db.c
inner join db.i on c_id = i_c
inner join db.l on c_id = l_c
group by c_id
having count(distinct i_attributeX) > count(distinct l_attributeY)
I seem to have problems with the distinct in linq. Any suggestions?
Cheers
How's this:
var result = db.c
.Where(c =>
c.i.Select(i => i.attributeX).Distinct().Count() >
c.l.Select(l => l.attributeY).Distinct().Count()
)
.Select(c => c.id);
or alternatively
var result = db.c
.Where(c =>
c.i.GroupBy(i => i.attributeX).Count() >
c.l.GroupBy(l => l.attributeY).Count()
)
.Select(c => c.id);

QueryOver with Select and OrderBy in NHibernate

I am wondering how do I order a group of results after a select with QueryOver. My query is the following:
CurrentSession.QueryOver<Book>()
.Where(b => b.Author.Name = "SimpleName")
.Select(Projections.Distinct(Projections.Property<Book>(b => b.Genre)))
.OrderBy<Genre>(g => g.Name) // this extension does not exist! How do I order for a Genre?
.List<Genre>()
How can I do?
Your query won't work to begin with. You first of all need to do a join, then you can do your order by and select projections.
Author author = null;
Genre genre = null;
CurrentSession.QueryOver<Book>()
.JoinAlias(b => b.Author, author)
.JoinAlias(b => b.Genre, genre)
.Where(() => author.Name == "SimpleName")
.OrderBy(() => genre.Name)
.Select(Projections.Distinct(Projections.Property<Book>(b => b.Genre)))
.List<Genre>();