How to create query of queries using LINQ? - c#

I'm trying to convert query of queries used in ColdFusion to LINQ and C#. The data come from data files, rather than from the database.
I converted the first query, but have no clue as to
how to use it to query the second query.
how to include count(PDate) as DayCount in the second query.
Below is the code using query of queries in ColdFusion:
First query
<cfquery name="qSorted" dbtype = "query">
SELECT OA, CD,PDate,
FROM dataQuery
GROUP BY CD,OA,PDate,
</cfquery>
Second query
<cfquery name="qDayCount" dbtype = "query">
SELECT OA, CD, count(PDate) as DayCount
FROM qSorted // qSorted is from the first query.
GROUP BY
OA, CD
ORDER BY
OA, CD
</cfquery>
Here's the first converted LINQ query, and it works fine:
var Rows = allData.SelectMany(u => u._rows.Select(t => new
{
OA = t[4],
CD = t[5],
PDate = t[0]
}))
.GroupBy(x => new { x.CD, x.OA, x.PDate })
.Select(g => new
{
g.Key.OA,
g.Key.CD,
g.Key.PDate
})
.ToList();
Here's the pseudo-code for the second LINQ query, which I need your assistance:
var RowsDayCount = Rows //Is this correct? If not, how to do it?
.GroupBy(x => new { x.OA, x.PDate, x.CD, })
.Select(g => new
{
g.Key.OA,
g.Key.CD,
g.Key.PDate,//PDate should be PDate.Distinct().Count() asDayCount
// See DayCount in cfquery name="qDayCount" above.
})
.OrderBy(u => u.OA)
.ThenBy(u => u.CD)
.ToList();

Your second query origionally wasn't grouping on PDate, but your translation is. That's wrong. If you want to count the number of PDates for each OA/CD pair, you need to not group on PDate. Once you've made that change, you can modify the Select to pull out all of the PDate values from the group, and count the distinct values.
.GroupBy(x => new { x.OA, x.CD, })
.Select(g => new
{
g.Key.OA,
g.Key.CD,
DayCount = g.Select(item => item.PDate).Distinct().Count(),
})

Related

I didn't true use order by in linq

Hi i develop web app with c#. I have sql query and i convert to linq but it's not working true because of order by
My sql query
Select TOP 3 HastalikIsmi From Hastaliklar group by HastalikIsmi order by Count(*) desc
My linq
public List<HastalikDto> GetHastalikDto()
{
using (SirketDBContext context = new SirketDBContext())
{
var result = from hastalik in context.Hastaliklar
group hastalik by hastalik.HastalikIsmi into isim
select new HastalikDto { HastalikIsmi = isim.Key };
return result.OrderBy(h => h.HastalikIsmi).Take(3).ToList();
}
}
Here's how you can do the order by on the count of each group and take the 3 with the highest count.
var result = context.Hastaliklar
.GroupBy(x => x.HastalikIsmi)
.OrderByDescending(grp => grp.Count())
.Select(grp => grp.Key)
.Take(3)
.ToList();

Order by and group by and sum using SQL

What I am trying to do is get the top 10 most sold Vegetables by grouping them by an Id passed by parameter in a function and ordering them by the sum of their Quantity. I don't know how to use SUM or (total) quite yet but I thought I'd post it here seeking help. If you need me offering you anything else I will be ready.
This is my code:
TheVegLinQDataContext db = new TheVegLinQDataContext();
var query =db.OrderDetails.GroupBy(p => p.VegID)
.Select(g => g.OrderByDescending(p => p.Quantity)
.FirstOrDefault()).Take(10);
And this is an image of my database diagram
Group orders by Vegetable ID, then from each group select data you want and total quantity:
var query = db.OrderDetails
.GroupBy(od => od.VegID)
.Select(g => new {
VegID = g.Key,
Vegetable = g.First().Vegetable, // if you have navigation property
Total = g.Sum(od => od.Quantity)
})
.OrderByDescending(x => x.Total)
.Select(x => x.Vegetable) // remove if you want totals
.Take(10);
Since this is not clear that you are passing what type of id as function parameter, I'm assuming you are passing orderId as parameter.
First apply where conditions then group the result set after that order by Total sold Quantity then apply Take
LINQ query
var result = (from a in orderdetails
where a.OrderId == orderId //apply where condition as per your needs
group a by new { a.VegId } into group1
select new
{
group1.Key.VegId,
TotalQuantity = group1.Sum(x => x.Quantity),
group1.FirstOrDefault().Vegitable
}).OrderByDescending(a => a.TotalQuantity).Take(10);
Lamda (Method) Syntax
var result1 = orderdetails
//.Where(a => a.OrderId == 1) or just remove where if you don't need to filter
.GroupBy(x => x.VegId)
.Select(x => new
{
VegId = x.Key,
x.FirstOrDefault().Vegitable,
TotalQuantity = x.Sum(a => a.Quantity)
}).OrderByDescending(x => x.TotalQuantity).Take(10);

Convert SQL query with multiple GroupBy columns to LINQ

SELECT
[TimeStampDate]
,[User]
,count(*) as [Usage]
FROM [EFDP_Dev].[Admin].[AuditLog]
WHERE [target] = '995fc819-954a-49af-b056-387e11a8875d'
GROUP BY [Target], [User] ,[TimeStampDate]
ORDER BY [Target]
My database table has the columns User, TimeStampDate, and Target (which is a GUID).
I want to retrieve all items for each date for each user and display count of entries.
The above SQL query works. How can I convert it into LINQ to SQL? Am using EF 6.1 and my entity class in C# has all the above columns.
Create Filter basically returns an IQueryable of the entire AuditLogSet :
using (var filter = auditLogRepository.CreateFilter())
{
var query = filter.All
.Where(it => it.Target == '995fc819-954a-49af-b056-387e11a8875d')
.GroupBy(i => i.Target, i => i.User, i => i.TimeStamp);
audits = query.ToList();
}
Am not being allowed to group by on 3 columns in LINQ and I am also not sure how to select like the above SQL query with count. Fairly new to LINQ.
You need to specify the group by columns in an anonymous type like this:-
var query = filter.All
.Where(it => it.Target == '995fc819-954a-49af-b056-387e11a8875d')
.GroupBy(x => new { x.User, x.TimeStampDate })
.Select(x => new
{
TimeStampDate= x.Key.TimeStampDate,
User = x.Key.User,
Usage = x.Count()
}).ToList();
Many people find query syntax simpler and easier to read (this might not be the case, I don't know), here's the query syntax version anyway.
var res=(from it in filter.All
where it.Target=="995fc819-954a-49af-b056-387e11a8875d"
group it by new {it.Target, it.User, it.TimeStampDate} into g
orderby g.Key.Target
select new
{
TimeStampDate= g.Key.TimeStampDate,
User=g.Key.User,
Usage=g.Count()
});
EDIT: By the way you don't need to group by Target neither OrderBy, since is already filtered, I'm leaving the exact translation of the query though.
To use GroupBy you need to create an anonymous object like this:
filter.All
.Where(it => it.Target == '995fc819-954a-49af-b056-387e11a8875d')
.GroupBy(i => new { i.Target, i.User, i.TimeStamp });
It is unnecessary to group by target in your original SQL.
filter.All.Where( d => d.Target == "995fc819-954a-49af-b056-387e11a8875d")
.GroupBy(d => new {d.User ,d.TimeStampDate} )
.Select(d => new {
User = d.Key.User,
TimeStampDate = d.Key.TimeStampDate,
Usage = d.Count()
} );

Converting SQL Query to LINQ for application

I have a query in TSQL that I am trying to convert to LINQ for use in our web application, but I am really struggling with this one. It is MVC5 with EF6 and the database is SQL Server 2008 R2. Any help is appreciated!
SQL Query
select MAX(ShipFromCompanyName) as Supplier, COUNT(*) as AllSupplierCount,
SUM(isnull(cast(TransportationCharges as decimal(18,2)),0)) as AllFreightCharges,
SUM(isnull(cast(TransportationCharges as decimal(18,2)),0)) * .45 as FreightSavings
from table
group by ShipFromCompanyName
order by ShipFromCompanyName
ShipFromCompanyName and TransportationCharges are both stored as varchar in the database, and unfortunately I am unable to change the data type of TransportationCharge to a decimal
LINQ
var Scorecard = (from upsid in _db.table select upsid).GroupBy(x => new { x.ShipFromCompanyName, x.TransportationCharges })
.Select(x => new
{
x.Key.ShipFromCompanyName,
SupplierCount = x.Count(),
FreightCharges = x.Key.TransportationCharges.Cast<decimal>().Sum(),
}).ToList();
I think you are going to need to do it post processing and not have SQL do it. Have SQL do as much as it can then do the rest in memory
var Scorecard = (from upsid in _db.table select upsid).GroupBy(x => new { x.ShipFromCompanyName, x.TransportationCharges })
.Select(x => new
{
x.Key.ShipFromCompanyName,
SupplierCount = x.Count(),
FreightCharges = x.Key.TransportationCharges,
}).AsEnumerable()
.Select (x => new
{
ShipFromCompanyName = ShipFromCompanyName ,
SupplierCount = SupplierCount ,
FreightCharges = FreightCharges.Cast<decimal>.Sum() ,
}
Didn't test this code but it should give you the idea.
var Scorecard = (from upsid in _db.table select upsid)
.GroupBy(x => new { x.ShipFromCompanyName, x.TransportationCharges })
.Select(x => new
{
x.Key.ShipFromCompanyName,
SupplierCount = x.Count(),
FreightCharges = x.Key.TransportationCharges.Select(tc=>decimal.Parse(tc)).Sum()*0.45,
}).ToList();
Since I didn't understand your query clearly I am not sure, but this may work.

Use Linq to return first result for each category

I have a class (ApplicationHistory) with 3 properties:
ApplicantId, ProviderId, ApplicationDate
I return the data from the database into a list, however this contains duplicate ApplicantId/ProviderId keys.
I want to supress the list so that the list only contains the the earliest Application Date for each ApplicantId/ProviderId.
The example below is where I'm currently at, but I'm not sure how to ensure the earliest date is returned.
var supressed = history
.GroupBy(x => new
{
ApplicantId = x.ApplicantId,
ProviderId = x.ProviderId
})
.First();
All advice appreciated.
Recall that each group formed by the GroupBy call is an IGrouping<ApplicationHistory>, which implements IEnumerable<ApplicationHistory>. Read more about IGrouping here. You can order those and pick the first one:
var oldestPerGroup = history
.GroupBy(x => new
{
ApplicantId = x.ApplicantId,
ProviderId = x.ProviderId
})
.Select(g => g.OrderBy(x => x.ApplicationDate).FirstOrDefault());
You are selecting first group. Instead select first item from each group:
var supressed = history
.GroupBy(x => new {
ApplicantId = x.ApplicantId,
ProviderId = x.ProviderId
})
.Select(g => g.OrderBy(x => x.ApplicationDate).First());
Or query syntax (btw you don't need to specify names for anonymous object properties in this case):
var supressed = from h in history
group h by new {
h.ApplicantId,
h.ProviderId
} into g
select g.OrderBy(x => x.ApplicationDate).First();

Categories