"select count(salary) from employee where employeeID = 10 group by salary" --- Its a SQL Query.
I need Linq Query which would retrieve me same output..?
Please Help me out i am new to Linq
You should also check :
Full aricle : SQL to LINQ ( Visual Representation )
from e in employee
where e.employeeid=10
group e by e.Salary
into grp
select new
{
Salary = grp.Key,
Count = grp.Count()
};
Your query puzzles me from the functional perspective: You want to count the number of different salaries for one employee?
Anyway, i think something like this would do also work (untested)
db.Employees.Where(e=>e.id == 10).Select(s=>s.salary).Distinct().Count()
Related
I have a database with the following schema:
Now, I'm trying to pull all landingpages for a domain and sort those by the first UrlFilter's FilterType that matches a certain group. This is the LINQ I've come up with so far:
var baseQuery = DbSet.AsNoTracking()
.Where(e => EF.Functions.Contains(EF.Property<string>(e, "Url"), $"\"{searchTerm}*\""))
.Where(e => e.DomainLandingPages.Select(lp => lp.DomainId).Contains(domainId));
var count = baseQuery.Count();
var page = baseQuery
.Select(e => new
{
LandingPage = e,
UrlFilter = e.LandingPageUrlFilters.FirstOrDefault(f => f.UrlFilter.GroupId == groupId)
})
.Select(e => new
{
e.LandingPage,
FilterType = e.UrlFilter == null ? UrlFilterType.NotCovered : e.UrlFilter.UrlFilter.UrlFilterType
})
.OrderBy(e => e.FilterType)
.Skip(10).Take(75).ToList();
Now, while this technically works, it's quite slow with execution times ranging from 10-30 seconds, which is not good enough for the use case. The LINQ is translated to the following SQL:
SELECT [l1].[Id], [l1].[LastUpdated], [l1].[Url], CASE
WHEN (
SELECT TOP(1) [l].[LandingPageId]
FROM [LandingPageUrlFilters] AS [l]
INNER JOIN [UrlFilters] AS [u] ON [l].[UrlFilterId] = [u].[Id]
WHERE ([l1].[Id] = [l].[LandingPageId]) AND ([u].[GroupId] = #__groupId_3)) IS NULL THEN 4
ELSE (
SELECT TOP(1) [u0].[UrlFilterType]
FROM [LandingPageUrlFilters] AS [l0]
INNER JOIN [UrlFilters] AS [u0] ON [l0].[UrlFilterId] = [u0].[Id]
WHERE ([l1].[Id] = [l0].[LandingPageId]) AND ([u0].[GroupId] = #__groupId_3))
END AS [FilterType]
FROM [LandingPages] AS [l1]
WHERE CONTAINS([l1].[Url], #__Format_1) AND #__domainId_2 IN (
SELECT [d].[DomainId]
FROM [DomainLandingPages] AS [d]
WHERE [l1].[Id] = [d].[LandingPageId]
)
ORDER BY CASE
WHEN (
SELECT TOP(1) [l2].[LandingPageId]
FROM [LandingPageUrlFilters] AS [l2]
INNER JOIN [UrlFilters] AS [u1] ON [l2].[UrlFilterId] = [u1].[Id]
WHERE ([l1].[Id] = [l2].[LandingPageId]) AND ([u1].[GroupId] = #__groupId_3)) IS NULL THEN 4
ELSE (
SELECT TOP(1) [u2].[UrlFilterType]
FROM [LandingPageUrlFilters] AS [l3]
INNER JOIN [UrlFilters] AS [u2] ON [l3].[UrlFilterId] = [u2].[Id]
WHERE ([l1].[Id] = [l3].[LandingPageId]) AND ([u2].[GroupId] = #__groupId_3))
END
OFFSET #__p_4 ROWS FETCH NEXT #__p_5 ROWS ONLY
Now my question is, how can I improve the execution time of this? Either by SQL or LINQ
EDIT: So I've been tinkering with some raw SQL and this is what I've come up with:
with matched_urls as (
select l.id, min(f.urlfiltertype) as Filter
from landingpages l
join landingpageurlfilters lpf on lpf.landingpageid = l.id
join urlfilters f on lpf.urlfilterid = f.id
where f.groupid = #groupId
and contains(Url, '"barz*"')
group by l.id
) select l.id, 5 as Filter
from landingpages l
where #domainId in (
select domainid
from domainlandingpages dlp
where l.id = dlp.landingpageid
) and l.id not in (select id from matched_urls ) and contains(Url, '"barz*"')
union select * from matched_urls
order by Filter
offset 10 rows fetch next 30 rows only
This performs somewhat okay, cutting the execution time down to ~5 seconds. As this is to be used for a table search I would however like to get it down even further. Is there any way to improve this SQL?
You're right to have a look at the generated SQL. In general, I would advise to learn SQL, write a performing SQL query and work your way back (either use a stored procedure or raw SQL, or design your LINQ query with that same philosophy.
I suspect this will be better (not tested):
var page = (
from e in baseQuery
let urlFilter = e.LandingPageUrlFilters.OrderBy(f => f.UrlFilterType).FirstOrDefault(f => f.UrlFilter.GroupId == groupId)
let filterType = urlFilter == null ? UrlFilterType.NotCovered : e.UrlFilter.UrlFilter.UrlFilterType
select new
{
LandingPage = e,
FilterType = filterType
}
).Skip(10).Take(75).ToList();
one of the way to improve the execution time is see execution plan in SSMS (SQL Server Management Studio).
After look on the execution plan you can design some indexes, or if you have no experiences with this, you can see if SSMS recommends some indexes.
Next try to create the indexes and execute the query again and see if execution time was improved.
Note: this is only one of many possible ways to improve execution time...
I have had an extensive look around on SE, tried all of the suggestions, checked out MSDN how to perform Left Join equivalent in LINQ to SQL and I have constructed my LINQ query according to MSDN example.
However, the result is not what SQL would return and I am completely lost as to where am I going wrong.
Here is some details:
I have two tables, Customers and Reports. A customer can submit many reports or none. In the current state I have many more reports than customers.
LINQ code:
var query = {from c in customers
join r in reports on c.Id equals r.Id into temp
from items in temp.DefaultIfEmpty()
select new {
c.Id,
LastReportDate = items?.DateCreated ?? DateTime.MinValue
}).ToList();
SQL code:
SELECT [Customers].[Id], R.LastReport AS LastReportDate FROM [Customers]
LEFT JOIN (
SELECT Reports.Id, MAX( [Reports].[Created] ) AS LastReport
FROM Reports GROUP BY Reports.Id
) AS r ON [Customers].[Id] = r.[Id]
The problem is that the query returns number of elements equal to number of reports. However, what I want is to get a list with all customers and for those who have submitted a report I wish to display the date of the most recent report, for those who have not submitted anything, I am happy to leave it NULL or DateTime.MinValue
Any help would be greatly appreciated. I guess I am missing a group by call somewhere in my LINQ code...
Im thinking probably something like this:
var query =
from c in customers
join r in reports on c.Id equals r.Id into g
select new
{
c.Id,
LastReportDate = g.Max(x => (DateTime?)x.Created)
};
you are now joining on join r in reports on c.Id equals r.Id into temp
this looks like: join on a customer.Id on Reports.Id, since you say there are 1 to many relation/rapport. I think your table will have a Reports.CustomerId. Is this correct?
So your query should something look like:
var results = customer.Where(c => c.Reports.Any())
.SelectMany(c => {c, c.Reports.Max(r => r.Created)})
.ToList();
the select comes out of my head, so i am probably missing something ;)
Have you tried LinqPad ? There you can type your linq-queries, and directly see your sql code and results. Works like a charm!
I have a query I know how to do in SQL but struggling to figure out the LINQ query. Here is the SQL.
SELECT ordNo, tranNo, COUNT(distinct custNo)
FROM orders
GROUP BY ordNo, tranNo
HAVING COUNT(distinct custNo) > 1
I don't feel like this is the same question that I see you marked as a duplicate. The linked question only groups on a single property. I've lost track of the Linq queries I've tried but here is one.
var countList = from o in orders
group o by new {o.orderNo, o.tranNo, o.custNo}
into grp
where grp.Key.custNo.Distinct().Count() > 1
select grp;
I tried the suggestion below but like someone commented you can't access the custNo property.
Just spitballing since I don't know the table structure.
context.orders
.GroupBy(o => new { o.ordNo, o.tranNo, o.custNo })
.Where(o => o.custNo.Distinct().Count() > 1)
.Select(o => new {
ordNo = o.ordNo,
tranNo = o.tranNo
});
I have the following SQL statement I'm trying to convert to Entity Framework.
SELECT S_NUMBER,A_NUMBER,FIRST_NAME,LAST_NAME
FROM EMPLOYEE WHERE S_NUMBER IN (
SELECT S_NUMBER
FROM EMPLOYEE
WHERE CO='ABC'
GROUP BY S_NUMBER
HAVING COUNT(*) > 1)
I've done some searching on using Group By in LINQ as well as sub-queries. I'm using LinqPad with a "C# Statement" and I came up with the following which based on some examples I found looks like it should work. However, I'm getting errors when trying to assign esn.S_NUMBER to sNumber in the anonymous object. The message says 'IGrouping' does not contain a definition for 'S_NUMBER'.
var result = from e in EMPLOYEE
where e.CO=="ABC"
group e by e.S_NUMBER into esn
select new
{
sNumber = esn.S_NUMBER
};
result.Dump();
I was under the impression that all the records would basically get put into a temp table called esn and I could be able to call the temptable.column name to assign it to my object that I will eventually return as a list.
You want to use Key instead of S_NUMBER. When grouping, the results get put into a IEnumerable<IGrouping>>. The grouping has a Key property which holds the key for that group, which in this case it's your S_NUMBER.
select new
{
sNumber = esn.Key
};
The following query should be a translation of the original SQL query. Instead of using a subquery, we're grouping and doing another from...in to "flatten" the sequence, and also checking that each grouping has a count > 1 like the original query.
var result = from e in EMPLOYEE
where e.CO=="ABC"
group e by e.S_NUMBER into esn
from e2 in esn
where esn.Count() > 1
select new
{
e.S_NUMBER,
e.A_NUMBER,
e.FIRST_NAME,
e.LAST_NAME
};
Since you're using the results of one query to filter another we can do a fairly direct transliteration of the query like so:
var result =
from e in EMPLOYEE
join f in (
from fe in EMPLOYEE
where fe.CO == 'ABC'
group null by S_NUMBER into grp
where grp.Count() > 1
select grp.Key
)
on e.S_NUMBER equals f
select new { e.S_NUMBER, e.A_NUMBER, e.FIRST_NAME, e.LAST_NAME };
Not only does this look a lot more like the original query but it should perform a bit faster (on MS SQL at least, can't speak for others) than the other form that might be simpler in LINQ but is much more complex when converted to SQL... four selects and a cross join, in my test version, vs two selects and an inner join for this one.
Of course if you prefer you can pull the inner query out as a separate IQueryable for clarity:
var filter =
from e in EMPLOYEE
where e.CO == 'ABC'
group null by S_NUMBER into grp
where grp.Count() > 1
select grp.Key;
var result =
from e in EMPLOYEE
join f in filter
on e.S_NUMBER equals f
select new { e.S_NUMBER, e.A_NUMBER, e.FIRST_NAME, e.LAST_NAME };
I want to convert the following SQL code into linq to sql but can't seem to find a way
select holder_name,agent_code,sum(total)
from agent_commission
group by agent_code
Can anyone help me? Am kinda stuck with this for quite a while.
Thanks in advance
UPDATE:
I tried the following
var query = (from p in context.Agent_Commissions
group p by new
{
p.agent_code
}
into s
select new
{
amount = s.Sum(q => q.total),
}
);
How do I select the other two columns? What am I missing?
In fact your SQL query works only when the corresponding relationship between holder_name and agent_code is 1-1, otherwise the Group by agent_code won't work. So your linq query should be like this:
var query = from p in context.Agent_Commissions
group p by p.agent_code into s
select new {
holder_name = s.FirstOrDefault().holder_name,
agent_code = s.Key,
amount = s.Sum(q => q.total)
};
Here is your linq query
from a in ctx.agent_code
group a by a.holder_name, a.code into totals
select { holder_name = a.holder_name,
code = a.code,
total = totals.Sum(t=>t.total)}
Given that you have linq2sql context in ctx variable and it has your table in it.