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)
Related
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
;
Hi I have this sql and have to translate into NHibernate QueryOver
SELECT S.Number, S.Description, S.BrandDescription, subquery.vendornumber, subquery.vendorname
FROM Stocks.Stock S left join
(select vendorNumber, VendorName, POLID, LastTransactionDate from
(
SELECT top 4 v.Number vendorNumber, v.Name VendorName, PLL.Id POLID, max(por.TransactionDate) as LastTransactionDate,
ROW_NUMBER() OVER(PARTITION BY v.Number ORDER BY max(por.TransactionDate) DESC) AS rk
FROM Purchasing.PurchaseOrderLineItem PLL
inner join Purchasing.PurchaseOrder po on PLL.PurchaseOrderId = po.Id
inner join Purchasing.PurchaseOrderVendor POV on po.Id = POV.PurchaseOrderId
inner join Purchasing.Vendor V on pov.VendorId = v.Id
left outer join Purchasing.PurchaseOrderReceipt POR on PLL.Id = por.PurchaseOrderLineItemId
group by v.Number, v.Name,PLL.Id
order by LastTransactionDate desc
) subquery
where subquery.rk = 1) B on PL.Id = b.POLID
Or just to explain it simply see its simplified version
Select * from master m
outer apply (select top 4 * From Details d where m.Id = d.Id order by someColumns desc)o
I think we cannot use subquery as derived table in nhibernate. If you have suggestions, please share.
Thanks
I was keep working on this and found that it could be very difficult if want to do totally with QueryOver. I want to show how I did this.
First I took all the vendors with StockID to join with StockQuery later.
var stockVendors =
Session.QueryOver<Vendor>(() => V)
.Left.JoinQueryOver(p => V.Stock, () => sstk)
.Where(sstk.Number !=null)
.OrderBy(Projections.Max(() => V.TransactionDate)).Desc()
.ThenBy(() => sstk.Number).Asc()
.ThenBy(() => sv.Number).Asc()
.SelectList(
lst =>
lst.SelectGroup(() => V.Name).WithAlias(() => svhModal.VendorName)
.SelectGroup(() => V.Number).WithAlias(() => svhModal.VendorNumber)
.SelectGroup(() => sstk.Number).WithAlias(() => svhModal.StockNumber)
.Select(Projections.Max(() => V.TransactionDate)).WithAlias(() => svhModal.LastTransactionDate)
)
.TransformUsing(Transformers.AliasToBean()).List();
Then select Stock only
var stockDetail = Session.QueryOver<Stock>(() => stk)
.Where(soneCriteria)
.SelectList(list => list
.Select(() => stk.Id).WithAlias(() => sdrModal.Id)
.Select(() => stk.Number).WithAlias(() => sdrModal.Number)
.TransformUsing(Transformers.AliasToBean<StockDetailReportModal>())
.List<StockDetailReportModal>();
IList<StockVendor> vlst2 = null;
IList<StockDetail> newStock = new List<StockDetail>();
Here starts two loops to fill List object with each stock and its 5 top vendors from vendors list. Loop from Stockdetail result from query and inside loop from vendor result filtered to outer loop stockid, get first 5 vendors only in loop, when done just return the result to report. Its working fine.
foreach (StockDetail ostk in stockDetail)
{
stkid = ostk.Number;
vlst2 = (from v in stockVendors where v.StockNumber == stkid orderby v.LastTransactionDate descending select v).ToList<StockVendor>();
vndrcnt = 0;
stok = new StockDetail
{
Id = ostk.Id,
Number = ostk.Number,
//// other fields too here
};
if (vlst2.Count() == 0)
{
newStock.Add(stok);
}
foreach (StockVendor vn in vlst2)
{
if (vndrcnt == 0)
{
stok.VendorName = vn.VendorName;
stok.VendorNumber = vn.VendorNumber;
// other fields here...
newStock.Add(stok);
}
else
{
newStock.Add(new StockDetail
{
Id = ostk.Id,
Number = ostk.Number,
VendorName = vn.VendorName,
VendorNumber = vn.VendorNumber,
// adding vendor information in stock record.
});
}
vndrcnt++;
if (vndrcnt >= 4)
break;
}
This solved my problem and achieved this after investigating many days. You may find better approach, so please share.
Here is the original logic
(scrape_datas = ScrapeData.find(
:all, :conditions =>
"artist_status = 'NOT_FOUND'
AND blacklisted = 1
AND extracted = 0
and not EXISTS(
SELECT * FROM artist_name_suggestions where original = artist_name
)
I've been able to split up the first part better
scrape_datas = ScrapeData.where(
:artist_status => 'NOT_FOUND',
:blacklisted => 1,
:extracted => 0
)
Although having issues getting the "and not EXISTS" query into the mix
and not EXISTS(
SELECT * FROM artist_name_suggestions where original = artist_name
)
Thanks!
Firstly you can extract simple scopes:
scope :not_found, where(:artist_status => 'NOT_FOUND')
scope :blacklisted, where(:blacklisted => 1)
scope :extracted, where(:extracted => 0)
Then add a query method (assume artist_name is a column of scrape_datas):
def self.no_suggestions
scrape_datas = ScrapeData.arel_table
suggestions = ArtistNameSuggestion.arel_table
where(ArtistNameSuggestion.where(
suggestions[:original].eq(scrape_datas[:artist_name])
).exists.not)
end
Now you can do something like this:
ScrapeData.not_found.blacklisted.extracted.no_suggestions
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);
I have the following SQL query:
SELECT C.ID, C.Name FROM Category C JOIN Layout L ON C.ID = L.CategoryID
JOIN Position P ON L.PositionID LIKE '%' + CAST(P.ID AS VARCHAR) + '%'
WHERE P.Code = 'TopMenu'
and following data
Position:
ID Code
1 TopMenu
2 BottomMenu
Category
ID Name
1 Home
2 Contact
3 About
Layout
ID CategoryID PositionID
1 1 1
2 2 1,2
3 3 1,2
With the above data, is it possible to convert the SQL query to LINQ or Lambda expression?
Any help is appreciated!
This might do what you want:
Layout
.Where(x => Position
.Where(y => y.Code == "TopMenu")
.Select(y => SqlClient.SqlMethods.Like(x.PositionID, "%" + y.ID.ToString() + "%")
).Count() > 0
).Join(
Category,
x => x.CategoryID,
x => x.ID,
(o,i) => new { ID = i.ID, Name = i.Name }
)
Although you might want to materialize the 'Position' sub query to save on time like so:
var innerSubQuery = Position.Where(y => y.Code == "TopMenu");
Layout
.Where(x => innerSubQuery
.Select(y => SqlClient.SqlMethods.Like(x.PositionID, "%" + y.ID.ToString() + "%")
).Count() > 0
).Join(
Category,
x => x.CategoryID,
x => x.ID,
(o,i) => new { ID = i.ID, Name = i.Name }
);
I do, however, agree with Jon that to really make your life simpler you should change the way you're handling the many-to-many relationship by creating a 'Layout_Position' table.
Well, you won't be able to express the second join as a join, because it's not an equijoin, but this should do it:
from c in category
join l in layout on c.Id equals l.CategoryId
from p in position
where p.Id.Contains(l.PositionId)
select new { c.Id, c.Name };
Note that your "contains/LIKE" clause will give you bad results when you've got more than 9 positions. There are better approaches to many-to-many relations than using a comma-separated list. (Such as an intermediate table.)