Get Rank from from Total LINQ Query - sql

I have two tables.First is CompetitionUsers and Competitionpoints.
There is foreign key relationship between tables with ParticipateID.
In CompetitionPoints Table there are points different points for multiple participateID.So I want to fetch Total Points and the Rank based on total points.So if there is multiple same total points for one participateID, the rank for that participateid should be same .Its same like student Total marks and Rank from that Mark.
Here is my code.
var competitionusers = (from c in db.CompetitionUsers
group c by new { c.ParicipateId, c.CompetitionPoints.FirstOrDefault().Points }
into g orderby g.Key.Points descending select
new { Points = db.CompetitionPoints.Where
(x => x.ParticiapteId == g.FirstOrDefault().ParicipateId).Sum(x => x.Points),
Rank = (from o in db.CompetitionUsers
group o by o.CompetitionPoints.FirstOrDefault().Points into l
select l).Count(s => s.Key > db.CompetitionPoints.
Where(x => x.ParticiapteId == g.FirstOrDefault().ParicipateId).Sum(x => x.Points)) + 1,
}).Where(x => x.Points != null).OrderByDescending(x => x.Points).AsQueryable();

If I understand your data model correctly, I think you could simplify to something like this:
var result = db.CompetitionUsers
// group by total points
.GroupBy(cu => cu.CompetitionPoints.Sum(cp => cp.Points))
// order by total points descending
.OrderByDescending(g => g.Key)
// calculate rank based on position in grouped results
.SelectMany((g, i) => g.Select(cu => new { Rank = i+1, TotalPoints = g.Key, CompetitionUser = cu }));

IQueryable<CompetitionLaderMadel> competitionUsers;
competitionUsers = (from c in db.CompetitionUsers
select new CompetitionLaderMadel
{
CompetitionName = c.Competition.CompetitionName,
CompetitionId = c.CompetitionId,
Points = db.CompetitionPoints.Where(x => x.ParticiapteId == c.ParicipateId).Sum(x => x.Points),
IsFollow = db.CrowdMember.Any(x => x.Following == userid && x.UserCrowd.UserID == c.UserId && x.Status != Constants.Deleted),
}).Where(x => x.Points != null && x.UserId != null).OrderByDescending(x => x.Points);
And then Wrote this Query
var q = from s in competitionUsers
orderby s.Points descending
select new
{
CompetitionName = s.CompetitionName,
CompetitionId = s.CompetitionId,
HeadLine = s.HeadLine,
UserId = s.UserId,
Points = s.Points,
Image = s.Image,
IsFollow = s.IsFollow,
UserName = s.UserName,
Rank = (from o in competitionUsers
where o.Points > s.Points
select o).Count() + 1
};

Related

.NET Core - EF - trying to "OR" built up Where's in a for loop

I try to filter data using multiple Where, built up in a loop. They must be chained with a OR
I read I should use PredicateBuilder from this page ttp://www.albahari.com/nutshell/predicatebuilder.aspx
problem : it does not return any data
I managed to debug the final query and noticed
the OR clauses are not present
a strange CAST line was present (which when I remove it, data appear)
here is the part that adds to the IQueryable:
IQueryable<Lead> data = context.Leads.AsQueryable();
List<ZipCodeRange> ranges = Tools.CreateZipCodesRanges();
var items = JsonConvert.DeserializeObject<List<MenuItem>>(leadsSearch.searchByZipcodes);
var activeRanges = items
.Where(item=>item.active)
.Select(item => ranges[item.id])
.ToList();
data = data.Where(d => activeRanges.Any(range => range.Min <= d.Company.ZipCodeNum &&
range.Max >= d.Company.ZipCodeNum));
var leads = await data.ToListAsync();
here is how I generate the ranges :
public static List<ZipCodeRange> CreateZipCodesRanges()
{
List<ZipCodeRange> zipCodeRanges = new List<ZipCodeRange>();
zipCodeRanges.Add(new ZipCodeRange() { Min = 1000, Max = 1495 });
zipCodeRanges.Add(new ZipCodeRange() { Min = 4000, Max = 7999 });
zipCodeRanges.Add(new ZipCodeRange() { Min = 1500, Max = 1999 });
zipCodeRanges.Add(new ZipCodeRange() { Min = 2000, Max = 2699 });
zipCodeRanges.Add(new ZipCodeRange() { Min = 2800, Max = 2999 });
zipCodeRanges.Add(new ZipCodeRange() { Min = 3000, Max = 3499 });
zipCodeRanges.Add(new ZipCodeRange() { Min = 3500, Max = 3999 });
zipCodeRanges.Add(new ZipCodeRange() { Min = 8000, Max = 8999 });
zipCodeRanges.Add(new ZipCodeRange() { Min = 9000, Max = 9999 });
return zipCodeRanges;
}
here is the generated query:
SELECT [l].[Id], [l].[AdminNotes], [l].[CompanyId], [l].[ContactId], [l].[CreationDate], [l].[CreationUserId], [l].[FacialValue], [l].[FedEce], [l].[FirstOrderDate], [l].[Identifier], [l].[LastOrderDate], [l].[Locked], [l].[ModificationDate], [l].[ModificationUserId], [l].[Notes], [l].[PartnerId], [l].[PrestationPercent], [l].[Products], [l].[Status], [l].[TicketsPerDay], [l].[ToTreat], [c].[Id], [c].[BceNumber], [c].[Box], [c].[City], [c].[Country], [c].[Name], [c].[Number], [c].[Size], [c].[Street], [c].[ZipCode], [c].[ZipCodeNum], [c0].[Id], [c0].[Civility], [c0].[CreationDate], [c0].[CreationUserId], [c0].[Email], [c0].[FirstName], [c0].[Language], [c0].[LastName], [c0].[Mobile], [c0].[ModificationDate], [c0].[ModificationUserId], [c0].[Phone], [c0].[Position], [c0].[Type]
FROM [leads] AS [l]
INNER JOIN [companies] AS [c] ON [l].[CompanyId] = [c].[Id]
INNER JOIN [contacts] AS [c0] ON [l].[ContactId] = [c0].[Id]
WHERE CAST(0 AS bit) = CAST(1 AS bit)
what am I doing wrong ?
thanks for your help
[edit]
System.InvalidOperationException: The LINQ expression 'DbSet<Lead>
.Join(
outer: DbSet<Company>,
inner: l => EF.Property<Nullable<int>>(l, "CompanyId"),
outerKeySelector: c => EF.Property<Nullable<int>>(c, "Id"),
innerKeySelector: (o, i) => new TransparentIdentifier<Lead, Company>(
Outer = o,
Inner = i
))
.Where(l => __activeRanges_0
.Any(range => (Nullable<int>)range.Min <= l.Inner.ZipCodeNum && (Nullable<int>)range.Max >= l.Inner.ZipCodeNum))' could not be translated.
This can be achieved without using PredicateBuilder by simply doing
var data = context.Leads
.Where(lead => items.Any(item => item.Min <= lead.Company.ZipCodeNum &&
item.Max >= lead.Company.ZipCodeNum))
Edit
For your updated code in the screenshot just remove the foreach at all and replace it with
var activeRanges = items
.Where(item.active)
.Select(item => ranges[item.id])
.ToList();
data = data.Where(d => activeRanges.Any(range=> range.Min <= d.Company.ZipCodeNum &&
range.Max >= d.Company.ZipCodeNum))
Since I cant get an answer, maybe EF is limited or something , so I did it this way:
List<int?> leadsIdsAll = new List<int?>();
foreach (var item in items)
{
if(item.active)
{
ZipCodeRange range = ranges[item.id];
List<int?> leadsIds = context.Leads.Where(l => range.Min <= l.Company.ZipCodeNum && range.Max >= l.Company.ZipCodeNum)
.Select(l => l.Id).ToList();
leadsIdsAll.AddRange(leadsIds);
}
}
data = data.Where(l => leadsIdsAll.Contains(l.Id));

How to select from a table by date using linqq

I have a table with products that can be in different locations to be submited to a rework task, but i need to pick only the most recent one based on the product.
I have the following table:
ID Tag Location task Date
1 1 A T1 2016/06/01
2 1 B T1 2016/07/01
3 2 A T1 2016/06/01
4 2 A T2 2016/07/01
i ned the select the row of the Tags with most recent Date to have in output the row with ID 2 and ID 4.
What is the correct linq query for that?
First group by tag then select max date
var result = db.Table.GroupBy(i => i.Tag).Select(i => new
{
Tag = i.Key,
Date = i.Max(t => t.Date)
}).ToList();
Updated 1 (Comment 1)
var result = (from x in db.Table
join z in (db.Table.GroupBy(i => i.Tag).Select(i => new
{
Tag = i.Key,
Date = i.Max(t => t.Date)
})
) on new { A = x.Tag, B = x.Date} equals { A = z.Tag, B = z.Date }
select x).ToList();
Update 2 (Comment 2)
var result = (from x in db.Table
join z in (db.Table.GroupBy(i => new { i.Tag, i.Task }).Select(i => new
{
Tag = i.Key.Tag,
Task = i.Key.Task,
Date = i.Max(t => t.Date)
})
) on new { A = x.Tag, B = x.Date, C = x.Task} equals { A = z.Tag, B = z.Date, C = z.Task }
select x).ToList();

sqlLinq Take higher RN number

Here is My Query
var sonuc = (from c in cd.Product
join pp in cd.Product_Picture_Mapping
on c.ID equals pp.ProductID
join pcc in cd.Picture
on pp.PictureID equals pcc.ID
select new ProductViewModel() { PicturePath = pcc.Path, ProductID = c.ID }).OrderBy(x => x.ProductID).ToList().AsEnumerable().Select((entry, index) => new ProductViewModel()
{
PicturePath = entry.PicturePath,
ProductID = entry.ProductID
}).OrderBy(x => x.ProductID).GroupBy(x => x.ProductID).Select(g => new { g, count = g.Count() })
.SelectMany(t => t.g.Select(b => b).Zip(Enumerable.Range(1, t.count), (j, i) => new { j.ProductID, j.PicturePath, rn = i }));
and OUTPUT;
PicturePath ProductID RN
samplepath1 4 1
samplepath2 5 1
samplepath3 10 1
samplepath4 10 2
samplepath5 10 3
so, i want to take one row that have same Product id by higher RN, like this.
PicturePath ProductID RN
samplepath1 4 1
samplepath2 5 1
samplepath5 10 3
How can i get like this ?
Thank you
Group by ProductID and select item with max RN from each group:
var result = from x in sonuc
group x by x.ProductID into g
select g.OrderByDescending(x => x.RN).First();

Convert sql to Lambda expression

Guy's I need a Lambda expression for this sql statement.
select GalleryId, Max(Bid)
from BidModels
where GalleryId in (select GalleryId from BidModels where UserId = (UserId))
group by GalleryId
I don't see why you need the subquery, given that you can just select all Bids where UserId = userid being passed in. With that in mind:
var userid = <whatever>;
var query = from b in BidModels
where b.UserId = userid
group by b.GalleryId into g
select new {Id = g.Key, MaxBid = g.Max(x => x.Bid)};
Here is how you can do it
var galleryIds = (bidModelses.Where(b => b.UserId == [YOURPARAMETER])
.Select(b => b.GalleryId));
var query = (bidModelses.Where(bm => galleryIds.Contains(bm.GalleryId))
.GroupBy(bm => bm.GalleryId)
.Select(gbm => new {gbm.Key, MaxBid = gbm.Max(p => p.BidId)}));
This seems to be the answer thanks for the help:
from b in BidModels
let MyGallery = from a in BidModels where a.UserId == (1) select new { a.GalleryId }
where MyGallery.Any()
group b.Bid by b.GalleryId into g
select new
{ Id = g.Key,
MaxBid = g.Max()
}

Trouble converting simple SQL to Linq

I'm pretty stuck on converting this to LINQ:
SELECT
COUNT(1) AS Registrations,
YEAR(Join_date) AS Year,
MONTH(Join_date) AS Month
FROM tblForumAuthor
GROUP BY YEAR(Join_date), MONTH(Join_date)
ORDER BY Year, Month
It's just a simple report, but I can't work out how to do the group by's and counts as the select new. I've only managed this pathetic attempt:
var q = (from c in db.tblForumAuthors
select new {Year = c.Join_date.Year,
Month = c.Join_date.Month,
Registrations = });
var results = db.tblForumAuthors.GroupBy(r => new {Year = r.Join_date.Year, Month = r.Join_date.Month})
.Select(g => new {Registrations = g.Count(), g.Key.Year, g.Key.Month})
.OrderBy(r => r.Year)
.ThenBy(r => r.Month)
from c in db.tblForumAuthors
group c by new {month = t.Join_Date.Month, year = t.Join_Date.Year}
into g select new {month = g.Key.month, year = g.Key.year, count = g.Count()}
Pipped to the post.... but this should do the trick. Notice how you can group by multiple fields by using an anonymous type. The properties of the group are available through the Key property of the grouping. Not sure if this will produce Count(1), though. IIRC it will be Count(*).
from c in db.tblForumAuthors
group c by new { c.Join_date.Year, c.Join_date.Month } into g
orderby g.Year, g.Month
select new {
Registrations = g.Count(),
g.Key.Year,
g.Key.Month
};
db.tblForumAuthors
.GroupBy(c => new {c.Join_date.Month, c.Join_date.Year})
.OrderBy(g => g.Key.Year).ThenBy(g => g.Key.Month)
.Select(g => new
{
Registrations = g.Count(),
Year = g.Key.Year
Month = g.Key.Month
});
I'll bet there are better ways to do it, but here's one.
If the table had two fields defined like this:
tblForumAuthor
==========================
Join_Date date
Name nvarchar(50)
You could get a report of the number of people joining in each Month+Year combo like this:
var db = new DataClasses1DataContext();
var report =
from a in db.tblForumAuthors
group a by new {Year = a.Join_Date.Year, Month = a.Join_Date.Month}
into g
select new
{
Year = g.Key.Year,
Month = g.Key.Month,
Registrations = g.Count()
};
foreach( var item in report)
{
Console.WriteLine(item.Year + " " + item.Month + " " + item.Registrations);
}
it is more like this - sorry don't have ability to test it
var results = from r in tblForumAuthorm
group r by r.Join_date into
select new { Year =r.Join_Date.Year, Month = r.join_date.month };