How to convert SQL to Linq with SUM calculation - c#

Can someone help me convert a SQL to Linq? I'm new to Linq and could use some help....
My SQL query string is;
SELECT *, Sum(RequisitionQTY*RequisitionPrice) as Total
FROM partrequisition
WHERE ReferenceNumber = searchModel.ReferenceNumber
GROUP BY 'ReferenceNumber'
what I have gotten so far is
var result = db.partrequisition
.Where(c => c.ReferenceNumber == searchModel.ReferenceNumber)
.GroupBy(c => c.ReferenceNumber)
.Select( <??> );
Not understanding how to do the calculation and build that into the Linq..
Thank you...

Like this? The result will be a list of sum for each reference numberger
var result = db.partrequisition
.Where(c => c.ReferenceNumber == searchModel.ReferenceNumber)
.GroupBy(c => c.ReferenceNumber)
// For each group, calculate the sum
.Select(g=> g.Sum( item=>item.RequisitionQTY*item.RequisitionPrice ))
.ToList();

Related

How to convert this SQL statement to Linq for C#

I am trying to convert my simple SQL statement into Linq format for my C# application but I always seem to struggle making the conversion. I downloaded linqpad and have been playing around with it but I'm still having issues with the proper format.
My SQL statement:
SELECT distinct PictureCity, PictureState
FROM Website_Gallery
GROUP BY PictureCity, PictureState, PictureDate
ORDER BY PictureCity, PictureState
The results are ordered by PictureCity and look like this:
Abington MA
Acton MA
Acushnet MA
Agawam MA
Andover MA
Arlington MA
Arlington TX
Ashby MA
Ashland MA
What I have so far in my C# application which I can't seem to get to work. (I suck at linq).
var Results = _context.Website_Gallery
.(g => g.PictureCity, g => g.PictureState).AsEnumerable()
.Select g
.GroupBy(g => g)
Seems like all you need is
var results = _context.Website_Gallery
.OrderBy(x => x.PictureCity)
.ThenBy(x => x.PictureState)
.Select(x => new { x.PictureCity, x.PictureState })
.Distinct();
that would be equivalent to the following SQL
SELECT distinct PictureCity, PictureState
FROM Website_Gallery
ORDER BY PictureCity, PictureState
because what you had did not need the group by
Note you can then either iterate that result in a foreach or tack a ToList to the end to materialize the query into memory.
SQL
SELECT distinct PictureCity, PictureState
FROM Website_Gallery
ORDER BY PictureCity, PictureState
Linq
var Results = _context.Website_Gallery
.Select(g => new { g.PictureCity, g.PictureState })
.Orderby(p => p.PictureCity).ThenBy(p => p.PictureState)
.Distinct().ToList();
Or you can also do this
var Results = _context.Website_Gallery
.GroupBy(x => new { PictureCity = x.PictureCity, PictureState = x.PictureState })
.Select(g => new { g.Key.PictureCity, g.Key.PictureState }).Orderby(p => p.PictureCity).ThenBy(p => p.PictureState)
.ToList();

Getting the count of most repeated records in Linq

I am working on an application in which I have to store play history of a song in the data table. I have a table named PlayHistory which has four columns.
Id | SoundRecordingId(FK) | UserId(FK) | DateTime
Now i have to implement a query that will return the songs that are in trending phase i.e. being mostly played. I have written the following query in sql server that returns me data somehow closer to what I want.
select COUNT(*) as High,SoundRecordingId
from PlayHistory
where DateTime >= GETDATE()-30
group by SoundRecordingId
Having COUNT(*) > 1
order by SoundRecordingId desc
It returned me following data:
High SoundRecordingId
2 5
2 3
Which means Song with Ids 5 and 3 were played the most number of times i.e.2
How can I implement this through Linq in c#.
I have done this so far:
DateTime d = DateTime.Now;
var monthBefore = d.AddMonths(-1);
var list =
_db.PlayHistories
.OrderByDescending(x=>x.SoundRecordingId)
.Where(t => t.DateTime >= monthBefore)
.GroupBy(x=>x.SoundRecordingId)
.Take(20)
.ToList();
It returns me list of whole table with the count of SoundRecording objects but i want just count of the most repeated records.
Thanks
There is an overload of the .GroupBy method which will solve your problem.
DateTime d = DateTime.Now;
var monthBefore = d.AddMonths(-1);
var list =
_db.PlayHistories
.OrderByDescending(x=>x.SoundRecordingId)
.Where(t => t.DateTime >= monthBefore)
.GroupBy(x=>x.SoundRecordingId, (key,values) => new {SoundRecordingID=key, High=values.count()})
.Take(20)
.ToList();
I have simply added the result selector to the GroupBy method call here which does the same transformation you have written in your SQL.
The method overload in question is documented here
To go further into your problem, you will probably want to do another OrderByDescending to get your results in popularity order. To match the SQL statement you also have to filter for only counts > 1.
DateTime d = DateTime.Now;
var monthBefore = d.AddMonths(-1);
var list =
_db.PlayHistories
.Where(t => t.DateTime >= monthBefore)
.GroupBy(x=>x.SoundRecordingId, (key,values) => new {SoundRecordingID=key, High=values.count()})
.Where(x=>x.High>1)
.OrderByDescending(x=>x.High)
.ToList();
I like the 'linq' syntax it's similar to SQL
var query = from history in _db.PlayHistories
where history.DateTime >= monthBefore
group history by history.SoundRecordingId into historyGroup
where historyGroup.Count() > 1
orderby historyGroup.Key
select new { High = historyGroup.Count(), SoundRecordingId = historyGroup.Key };
var data = query.Take(20).ToList();
You´re allmost done. Just order your list by the count and take the first:
var max =
_db.PlayHistories
.OrderByDescending(x=>x.SoundRecordingId)
.Where(t => t.DateTime >= monthBefore)
.GroupBy(x=>x.SoundRecordingId)
.OrderByDescending(x => x.Count())
.First();
This gives you a single key-value-pair where the Key is your SoundRecordingId and the value is the number of its occurences in your input-list.
EDIT: To get all records with that amount chose this instead:
var grouped =
_db.PlayHistories
.OrderByDescending(x => x.SoundRecordingId)
.Where(t => t.DateTime >= monthBefore)
.GroupBy(x => x.SoundRecordingId)
.Select(x => new { Id = x.Key, Count = x.Count() }
.OrderByDescending(x => x.Count)
.ToList();
var maxCount = grouped.First().Count;
var result = grouped.Where(x => x.Count == maxCount);
This solves the problem by giving you what you asked for. Your query in LINQ, returning just the play counts.
var list = _db.PlayHistories.Where(x => x.DateTimeProp > (DateTime.Now).AddMonths(-1))
.OrderByDescending(y => y.SoundRecordingId.Count())
.ThenBy(z => z.SoundRecordingId)
.Select(xx => xx.SoundRecordingId).Take(20).ToList();

Lambda Group By Max

I have this query.
select distinct game_id, max(event_number) as LatestEvent from Source group by game_id
But I would like this converted to its Linq or Lambda equivalent and I havent found a way to do so properly. Can someone advise.
Thanks for your time.
var q = db.Table
.GroupBy(x => x.game_id)
.Select(g => new { game_id = g.Key, LatestEvent = g.Max(x => x.event_number) });

Getting Rounded Values in the final result of Linq Query

How can the below linq Query be modified such that i can get a Rounded figure of values.
var result=GetStudentsWithTheirMarks()
.OrderByDescending(x => Math.Round(x.PercentageScore)).Take(5)
.OrderBy(x => x.PercentageScore);
Please ignore the presence of two order by clause as this is done for with a purpose.
GetStudentsWithThierMarks returns Student List with their FirstName and PercentageScore.
I believe in the above query Math.Round is only applicable when during order by operation so final result still contains values in decimal places whereas i am only interested to see rounded figures with integer values. I just cant figure out the syntax.
You just need a Select :
var result= GetStudentsWithTheirMarks()
.OrderByDescending(x => Math.Round(x.PercentageScore))
.Take(5)
.OrderBy(x => x.PercentageScore)
.Select(x => Math.Round(x.PercentageScore));
You can store this value in an anonymous type:
var result = GetStudentsWithTheirMarks()
.Select(s => new
{
Student = s,
RoundedPercentageScore = Math.Round(s.PercentageScore)
})
.OrderByDescending(x => x.RoundedPercentageScore )
.Take(5)
.OrderBy(x => x.Student.PercentageScore);
Now you can access it in this way:
foreach(var x in result)
Console.WriteLine("RoundedPercentageScore: " x.RoundedPercentageScore);

EF Linq to Entities Query with groupby sum and min

I am trying to make a Linq to Entities Query working but I can't figure it out.
This is my my SQL query which is working fine:
SELECT SUM(ca.PointValue) as Points, ua.UserFBID, MIN(ua.[Date]) as FirstDate
FROM [LeaderOfNow].[dbo].[QuestionAnswer] ca
inner join [LeaderOfNow].[dbo].[LONUserAnswers] ua
on ca.Id = ua.AnswerId
group by ua.UserFBID
order by Points desc, FirstDate asc
An so far my best attempt is:
var leaders = db.LONUserAnswers
.GroupBy(a => a.UserFBID)
.Select(a =>
new
{
FBID = a.Key,
CurrentPoints = a.Select(v => v.QuestionAnswer.PointValue).Sum(),
FirstAnswered = a.Min(v => v.Date)
})
.OrderByDescending(a => a.CurrentPoints)
.OrderBy(a => a.FirstAnswered)
.Take(10)
.ToList();
However that renders a mess of sql and only respect the first order by and not the second, which I need to work. Any suggestions on what am I doing wrong? Thank you for the help.
When you chain OrderBy-Functions you have to use ThenBy() or ThenDescendingBy() for the latter.

Categories