I have the below sql query that i am able to conert into LINQ
select count(*), BatchID
from TimeSheetHeader
group by BatchID having count(*) > 1
converts to
var duplicateBatchIDList = from c in _db.TimeSheetHeaders
group c by c.BatchID into grp
where grp.Count() > 1
select grp;
But now i am trying to throw an extra column that isnt included in the group by. I have the SQL query
select count(*), BatchID, TimeSheetCreationDate = min( TimeSheetCreationDate )
from TimeSheetHeader
where TimeSheetCreationDate >= CURRENT_TIMESTAMP
group by BatchID having count(*) > 1
But i am not sure how this convert over to LINQ
from c in _db.TimeSheetHeaders
where c.TimeSheetCreationDate >= CURRENT_TIMESTAMP
group c by c.BatchID into grp
where grp.Count() > 1
select new
{
BatchID = grp.Key,
Count = grp.Count(),
TimeSheetCreationDate = grp.Min(x => x.TimeSheetCreationDate)
}
Here you can find the lambda expression version of the query:
var result = TimeSheetHeader
.Where(t => t.TimeSheetCreationDate >= TIMESTAMP)
.GroupBy(t => t.BatchID)
.Where(g => g.Count() > 1)
.Select(g => new
{
Count = g.Count(),
BatchID = g.Key,
TimeSheetCreationDate = g.Min(x => x.TimeSheetCreationDate)
})
.ToList();
I slightly modified Magnus's answer
var duplicateBatchIDList = (from c in _db.TimeSheetHeaders
group c by c.BatchID into grp
where grp.Count() > 1
select new
{
BatchID = grp.FirstOrDefault().BatchID,
TimeSheetCreationDate = grp.Min(x => x.TimeSheetCreationDate)
}).Where(x => x.TimeSheetCreationDate <= DateTime.Now);
Related
Need some help translating below query to LINQ.
;With BookingWithLastStatus
as
(
Select *, Rnk = ROW_NUMBER() over (partition by BookingId order by Id desc)
from BookingStatus
)
Select *
from BookingWithLastStatus
where Rnk=1 AND StatusId = 3
I've done LINQ below but it is not getting the correct records.
var BookStatus = from p in _context.Set<BookingStatus>()
where p.StatusId == 3
group p by p.BookingId into opt
select new {
BookingId = opt.Key,
Id = opt.Max(x => x.Id)
};
The SQL query is getting 1 record only which is correct and my LINQ is getting multiple records.
UPDATE:
I did like this:
Get all the BookingStatus first
var GetAllBookStatus = await _context.Set<BookingStatus>()
.ToListAsync();
Then do the filtering based from the SQL Query I need.
var FilteredBookStatus = GetAllBookStatus
.OrderByDescending( x => x.Id )
.GroupBy(person => person.BookingId)
.Select( group => new { Group = group, Count = group.Count() } )
.SelectMany( groupWithCount =>
groupWithCount.Group.Select( b => b)
.Zip(
Enumerable.Range( 1, groupWithCount.Count ),
( b, i ) => new {
b.Id,
b.BookingId,
b.BookingMWABId,
b.BookStatus,
b.CreatedBy,
b.CreatedDate,
b.Destination,
b.InternalStatus,
b.LineNum,
b.ModifiedBy,
b.ModifiedDate,
b.Module,
b.ReasonCode,
b.ReceivedBy,
b.RefNo,
b.StatusId,
b.TimeStamp,
RowNumber = i }
)
)
.Where(a => a.StatusId == 3 && a.RowNumber == 1)
.ToList();
But I'm not so confident on Getting all records, as it will grow some time. Is there anything I can change from my code?
With EF core 6.x, you can do the following. It is not optimal case as in your SQL, but should work:
var BookStatus =
from p in _context.Set<BookingStatus>()
group p by p.BookingId into g
select g.OrderByDescending(x => x.Id).First();
BookStatus = BookStatus.Where(p => p.StatusId == 3);
Or another variant
var BookStatus = _context.Set<BookingStatus>().AsQueryable();
BookStatus =
from d in BookStatus.Select(d => new { d.BookingId }).Distinct()
from p in BookStatus
.Where(p => p.BookingId == d.BookingId)
.OrderByDescending(p => p.Id)
.Take(1)
select p;
BookStatus = BookStatus.Where(p => p.StatusId == 3);
I have an EF query that contains a number of aggregate sub queries (Count, Sum and Max). There are two problems.
I need the joins on the sub queries to be left joins so that records are returned even if there are no results in the aggregate sub queries. At present, records are only returned if all sub queries return records.
The resulting list of WholesaleCustomerAndAggregateOrders objects that are returned contain a Contact object that needs to also include Addresses and Counties. I added Include(c => c.Addresses.Select(a => a.Country)) to the query but the Contact objects don't contain any Address objects.
Any assistance with either issue would be appreciated. Full query below.
var month1Date = DateTime.Today.AddMonths(-1);
var month3Date = DateTime.Today.AddMonths(-3);
var month6Date = DateTime.Today.AddMonths(-6);
var month12Date = DateTime.Today.AddMonths(-12);
var db = GetNewContext();
var qry = from c in db.Contacts
.Include(c => c.Addresses.Select(a => a.Country))
join orderCount in
(
from o in db.WholesaleOrders
group o by o.ContactId into g
select new
{
ContactId = g.Key,
TotalOrders = g.Count()
}
) on c.Id equals orderCount.ContactId
join month1Value in
(
from o in db.WholesaleOrders
where o.OrderDate >= month1Date
group o by o.ContactId into g
select new
{
ContactId = g.Key,
TotalValue = g.Sum(r => r.LineItems.Sum(l => l.QuantityOrdered * l.Price))
}
) on c.Id equals month1Value.ContactId
join month3Value in
(
from o in db.WholesaleOrders
where o.OrderDate >= month3Date
group o by o.ContactId into g
select new
{
ContactId = g.Key,
TotalValue = g.Sum(r => r.LineItems.Sum(l => l.QuantityOrdered * l.Price))
}
) on c.Id equals month3Value.ContactId
join month6Value in
(
from o in db.WholesaleOrders
where o.OrderDate >= month6Date
group o by o.ContactId into g
select new
{
ContactId = g.Key,
TotalValue = g.Sum(r => r.LineItems.Sum(l => l.QuantityOrdered * l.Price))
}
) on c.Id equals month6Value.ContactId
join month12Value in
(
from o in db.WholesaleOrders
where o.OrderDate >= month12Date
group o by o.ContactId into g
select new
{
ContactId = g.Key,
TotalValue = g.Sum(r => r.LineItems.Sum(l => l.QuantityOrdered * l.Price))
}
) on c.Id equals month12Value.ContactId
join month12Quantity in
(
from o in db.WholesaleOrders
where o.OrderDate >= month12Date
group o by o.ContactId into g
select new
{
ContactId = g.Key,
OrderCount = g.Count()
}
) on c.Id equals month12Quantity.ContactId
join lastOrderDate in
(
from o in db.WholesaleOrders
group o by o.ContactId into g
select new
{
ContactId = g.Key,
LastOrderDate = g.Max(r => r.OrderDate)
}
) on c.Id equals lastOrderDate.ContactId
select new WholesaleCustomerAndAggregateOrders
{
Contact = c,
TotalOrders = orderCount.TotalOrders,
Month1Value = month1Value.TotalValue,
Month3Value = month3Value.TotalValue,
Month6Value = month6Value.TotalValue,
Month12Value = month12Value.TotalValue,
Month12OrderCount = month12Quantity.OrderCount,
LastOrderDate = lastOrderDate.LastOrderDate
};
return await qry.ToListAsync();
How about this:
db.WholesaleOrders
.GroupBy(o => o.ContactId)
.Select(a => new {
a.Key,
TotalOrders = a.Count(),
LastOrderDate = a.Max(r => r.OrderDate),
Month1Value = a.Where(b => b.OrderDate >= month1Date).Sum(r => r.LineItems.Sum(l => l.QuantityOrdered * l.Price),
Month3Value = a.Where(b => b.OrderDate >= month3Date).Sum(r => r.LineItems.Sum(l => l.QuantityOrdered * l.Price),
Month6Value = a.Where(b => b.OrderDate >= month6Date).Sum(r => r.LineItems.Sum(l => l.QuantityOrdered * l.Price),
Month12Value = a.Where(b => b.OrderDate >= month12Date).Sum(r => r.LineItems.Sum(l => l.QuantityOrdered * l.Price)
}).ToListAsync();
UPDATE: Add another property to projection:
Addresses = db.Addresses.Where(ad => ad.ContactId == a.Key);
where db is your context, and ad.ContactId is FK of the contact in Address table.
For this to work, multipleactiveresultsets property of the connection must be set to True.
I am having a VERY hard time converting my simple SQL query to LINQ...
SELECT Id
,Location
,SUM( CASE
WHEN TransactionType = 'Out' THEN [Quantity] * -1
ELSE Quantity
END) AS StockQuantity
FROM Transactions
WHERE Id = 123
GROUP BY Id, Location
here is my best WRONG attempt...
var result = db.Transactions
.Where(r => r.Id == 123)
.GroupBy(r => r.Id, r => r.Location)
.Select(group => new
{
Id = r.Id,
Location = r.Location,
Quantity = sum(r.TransactionType == 2 ? r.Quantity * -1 : r.Quantity),
});
Thanks in advance
You are not using your grouped values. Your query should be like:
var result = db.Transactions
.Where(r => r.Id == 123)
.GroupBy(r => new { r.Id, r.Location} )
.Select(grp => new
{
Id = grp.Key.Id,
Location = grp.Key.Location,
Quantity = grp.Sum(t=> t.TransactionType == 2 ? t.Quantity * -1 : t.Quantity),
});
I would also use a different variable name than group in projection (Select) since it is a contextual keywords (with query expression)
I have an SQL expression
select S.SpecialtyName, COUNT(distinct SUC.SiteUserId) as Subscribers
from SiteUserContent SUC Inner join
Specialties S on SUC.SpecialtyId = S.SpecialtyId Inner join
SiteUser SU on SUC.SiteUserId = SU.SiteUserId
where SU.DeletedFlag = 0
group by S.SpecialtyName
Order by S.SpecialtyName
What will be the corresponding LINQ expression for the same?
from suc in context.SiteUserContent
join s in context.Specialties on suc.SpecialtyId equals s.SpecialtyId
join su in context.SiteUser on suc.SiteUserId equals su.SiteUserId
where su.DeletedFlag == 0
select new { suc.SiteUserId, s.SpecialityName } into x
group x by x.SpecialityName into g
orderby g.Key
select new {
SpecialityName = g.Key,
Subscribers = g.Select(i => i.SiteUserId).Distinct().Count()
}
Generated SQL will not be same, but I think result of query execution should be same.
var results = contex.SiteUserContent
.Join(context.Specialties, suc => suc.SpecialtyId, s => s.SpecialtyId, (suc, s) => new { suc, s })
.Join(context.SiteUser, i = i.suc.SiteUserId, su => su.SiteUserId, (i, su) => new { suc = i.suc, s = i.s, su = su })
.Where(i => i.su.DeletedFlag == 0)
.GroupBy(i => i.s.SpecialtyName)
.Select(g => new {
SpecialityName = g.Key,
Subscribers = g.Select(i => i.suc.SiteUserId)
.Distinct()
.Count()
})
.OrderBy(i => i.SpecialityName);
I have a SQL and having a hard time to convert it to LINQ. Are there any other tools that can convert SQL to LINQ? I heard Linqer and tried it but it doesn't allow you to query on the Junction/Join Table of a Many-to-Many relationship tables. In any case here's the SQL that I need to convert to LINQ or even lambda.
SELECT A.*
FROM
( SELECT TOP 10 T2.ID,
T2.Name,
SUM(T1.Column1 + T1.Column2 + T1.Column3) AS Total
FROM POS.dbo.Table1 T1
INNER JOIN POS.dbo.Table2 T2 on T2.ID = T1.ID
WHERE T2.ID IN
(
SELECT ID FROM POS.dbo.Table3 WHERE [Id] = 1
)
AND [Date] BETWEEN '2011-11-09 00:00:00' AND '2011-11-09 23:59:59'
GROUP BY T2.ID, T2.Name
ORDER BY Total DESC
) A
ORDER BY Name ASC
Here is my first attempt:
var query = db.Table1
.Include(e => e.Table2)
.Where(x => x.Date >= '2011-11-09 00:00:00'
&& x.DateCreated <= '2011-11-09 23:59:59')
.Where(y => y.Table2.Table3.Any(u => u.Id == 1))
.Take(10);
One of the things I like most about Linq is that it will combine queries together, so I break a complicated query into subqueries and let Linq recombine them all.
Using that basis, does something like this work.
DateTime startDate = new DateTime(2011,11,9);
DateTime endDate = new DateTime(2011,11,9,23,59,59);
var table3Ids = (from r in Pos.dbo.Table3 where id = 1 select r.id) ;
var query1 =
(
from t1 in Pos.dbo.Table1
where t1.Table2.Id == 1 && t1.Date >= startDate && t1.Date <= endDate
where table3Ids.Contains(t1.Table2.Id)
group t1 by new { t1.Table2.Id , t1.Table2.Name} into results
select new
{
results.Key.Id ,
results.Key.Name ,
Total = results.Sum(r=> (r.Column1 + r.Column2 + r.Column3))
}
);
var query2 = (from r in query1 orderby r.Total descending select r).Take(10);
var query3 = (from r in query2 orderby r.Name select r);
var list = query3.ToList();
Here's my shot - it's a bit hard without knowing the actual data structure or the expected results:
var query = db.Table1
.Join(db.Table2, table1 => table1.Id, table2 => table2.Id, (t1, t2) => new {
Id = t2.Id,
Name = t2.Name,
Total = (t1.Column1 + t1.Column2 + t1.Column3),
Date = t1.Date //you didn't use a table alias for this field, so I'm not sure which table it comes from
})
.Where(x => x.Date >= new DateTime(2011, 11, 9)
&& x.DateCreated <= new DateTime(2011, 11, 9, 23, 59, 59))
.Join(db.Table3, x => x.Id, table3 => table3.Id, (x, t3) => new {
Id = x.Id,
Name = x.Name,
x.Total
})
.Where(x => x.Id == 1)
.OrderByDescending(x => x.Total)
.ThenBy(x => x.Name)
.Take(10)
.ToList()
Because that might be the craziest Linq statement I've ever written, don't assume it'll work the first time, but it's at least a good starting point.