having difficulty writing this in LINQ - linq

The application is a basic stock-analysis app.
The data-set looks like this:
`ABC, True, 21/09/2012, 101.34
ABC, False, 21/09/2012, 202.45
CDE, True, 21/09/2012, 345.67
ABC, True, 22/09/2012. 456.78
`
The SQL is here:
SELECT TickerCode, Australian from Stk_ClosingPrices group by TickerCode,
Australian having count(*) >= #daysToAverageOver order by TickerCode
What I would like as a result would be grouping by the first two fields,and a count of how many in each group. For the above that would be:
ABC, True, 2
ABC, False, 1
CDE, True, 1
And then I would like to return only those with Count > parameter passed in.
The algorithm is going to calculate a 20-day moving average, so in English the query is 'Give me the keys of stocks with more than 20 data records'
This is how far I have got, but I can't get the Count right, it is always the same for every group.
var query = (from cp in this.ObjectContext.stk_ClosingPrices group cp by new {
cp.TickerCode, cp.Australian
}
into grp
select new {
grp.Key.TickerCode, grp.Key.Australian,
Count = grp.Distinct()
}).ToList();
I have seen an example similar with a grp.Sum(Quantity) but could not seem to be able to re-cast that to .Count() predicate.
Many thanks,

Try
var query1 = (from cp in this.ObjectContext.stk_ClosingPrices group cp by new {
cp.TickerCode, cp.Australian
}
into grp
select new {
grp.Key.TickerCode, grp.Key.Australian,
Count = grp.Count()
});
var results = (from r in query where r.Count > 20 orderby r.TickerCode select r).ToList();
Will actually produce SQL like
SELECT TickerCode, Australian, Count
FROM (
SELECT COUNT(*) AS Count, TickerCode, Australian
FROM Stk_ClosingPrices
GROUP BY TickerCode, Australian
) AS t1
WHERE t1.Count > 20
Order By t1.TickerCode

Related

following linq performing left outer join instead of inner join

I cannot see where the problem lies with the following code. I am trying to retrieve those employees who are named as responsibles for certain vacancie. I have about 20 vacancies in my DB assigned to some 16 employees and about 1801 employee records in the employees table. The code always returns a result with 1801 entries.
from emp in container.Employees
join p in container.Vacancies
on emp.EMPID equals p.ResponsibleOfficer into j
group j by new {k1=emp.EMPID,k2=emp.NAME} into g
select new { EmpId = g.Key.k1, Name = g.Key.k2 , Count = g.Count()}
I want something similar to this
select emp.EmpId,emp.Name,Count(*) as count
from Vacancies p, Employees e
where p.ResponsibleOfficer=e.EmpId
group by e.EmpId,e.Name
any help is much appreciated. thanks
You're using join ... into. That will always return a single result for each element of the original sequence, even if there are no matches in the right sequence.
You can filter out entries with no elements in j using a where clause:
from emp in container.Employees
join p in container.Vacancies
on emp.EMPID equals p.ResponsibleOfficer into j
where j.Any()
group j by new {k1=emp.EMPID,k2=emp.NAME} into g
select new { EmpId = g.Key.k1, Name = g.Key.k2 , Count = g.Count()}
Or you could just use an inner join to start with - but I don't understand your current grouping well enough to see what you're trying to do. What is your group by clause for?
EDIT: If it was really just to group by employee, you're already doing that. You can change the code to:
from emp in container.Employees
join p in container.Vacancies
on emp.EMPID equals p.ResponsibleOfficer into j
where j.Any()
select new { Employee = emp, Count = j.Count()}
Basically, after the join you've got two range variables in scope: emp (the "current" employee) and j (all the relevant vacancies matching that employee). You're just trying to count j for each employee, right?
I'm using lambda, but works:
container
.Employees
.Join(container.Vacancies, l => l.EmpId, e => e.ResponsibleOfficer, (l, e) => new { l.EmpId, l.Name })
.GroupBy(g => new { g.EmpId, g.Name })
.Select(s => new { EmpId = s.Key.EmpId, Name = s.Key.Name, Count = s.Count() });

How to join two tables and make group by in Linq

I have a question about Linq select statement. I am new to Linq so any help will be very helpful. I did a lot of research but I still didn't manage to write down correct Linq statement.
I have this two tables and attributes:
Table Titles(title_id(PK), title) and
Table Sales(title_id(PK), qty)
where are title_id and title string values and qty is a number which represents some quantity.
I need to write a select which will take five most selling titles from this two tables.
So, I need to make sum from qty (we can have more records with the same Sales.title_id attribute) and make group by title_id and order by sum(qty) descending and then return attributes title and title_id.
How can I make suitable solution for my question?
Regards,
Dahakka
You can do group join of tables by title_id (each group g will represent all sales of joined title). Then select title description and total of sales for that title. Order result by totals, select title and take required number of top sales titles:
var query = (from t in db.Titles
join s in db.Sales on t.title_id equals s.title_id into g
select new { Title = t.title, Total = g.Sum(x => x.qty) } into ts
orderby ts.Total descending
select ts.Title).Take(5);
Resulting SQL will look like:
SELECT TOP (5) [t2].[title] AS [Title], [t2].[value] AS [Total]
FROM (
SELECT [t0].[title_id], (
SELECT SUM([t1].[qty])
FROM [Sales] AS [t1]
WHERE [t0].[title_id] = [t1].[title_id]
) AS [value]
FROM [Titles] AS [t0]
) AS [t2]
ORDER BY [t2].[value] DESC
Following is the linq query in method syntax
sales.GroupBy(s=>s.title_id)
.Select ( x =>
new {
Title_id = x.Key,
Sales= x.Sum (x=> x.qty)
})
.OrderByDescending(x=>x.Sales).Take(5)
.Join( titles,
sale=>sale.Title_id,
title=> title.title_id,
(sale, title)=> new
{
Title = title.Title,
TotalSales=sale.Sales
}
);

Linq - Join results from 2 columns from same table

I would like to join results from a table, to sum up the results from a where condition on 2 different rows, as this code:
var a = (from o in _DB.Services
where (o.description.Contains(searchText) || o.nom.Contains(searchText))
orderby o.date
select new { results = ?????, id = ?????? }).Take(maxResults).ToList();
What can I put, in order to take into account the results=???? and id=???
Thanks
Based on your comment, can't you just do the following?
var a = (from o in _DB.Services
where (o.description.Contains(searchText) || o.nom.Contains(searchText))
orderby o.date
select new
{
results = o.description,
id = o.nom
})
.Take(maxResults)
.ToList();

Translate SQL query without FROM clause to LINQ

How to translate query like "select 1, 2" (i.e. without FROM clause) to LINQ statement?
Thanks!
I need to get permissions for a set of user groups. In SQL it looks like
SELECT *
FROM Permission p
INNER JOIN (SELECT GroupID
FROM [Group]
UNION ALL
SELECT 555) AS g
ON (g.GroupID = p.GroupID)
In my case I need to programmatically add a certain code instead "555". I wouldn't like to write special SQL function for that.
I guess you just want to create an anonymous type
var anonymous = new { Column1 = 1, Column2 = 2 };
Edit - Based on Comments
Depending on what your Select projection is you could do something simple like this:
If it is a Int:
var query = (from per in context.permissions
select per).AsEnumerable()
.Concat( new int[] { 1, 2 });
If it is a 'Class'
var query = (from per in context.permissions
select per).AsEnumerable()
.Concat(new CustomClass[]
{
new CustomClass()
{
Prop1= 1
},
}
);
You could also change .Concat to .Union
Why do you need this to be linq?
var numbers = new int[] { 1, 2 };
I suppose
var numbers = Enumerable.Range(1,2);

Entity Framework T-Sql "having" Equivalent

How can I write a linq to entities query that includes a having clause?
For example:
SELECT State.Name, Count(*) FROM State
INNER JOIN StateOwner ON State.StateID = StateOwner.StateID
GROUP BY State.StateID
HAVING Count(*) > 1
Any reason not to just use a where clause on the result?
var query = from state in states
join stateowner in stateowners
on state.stateid equals stateowner.stateid
group state.Name by state.stateid into grouped
where grouped.Count() > 1
select new { Name = grouped.Key, grouped.Count() };
I believe you can use a GroupBy followed by a Where clause and it will translate it as a Having. Not entirely sure though.
If you want to compare a variable that is not in the group by (Ex: age), then it would be:
var duplicated = (
from q1 in db.table1
where (q1.age >= 10 )
group q1 by new { q1.firstName, q1.lastName } into grp
where (grp.Count() > 1 )
select new
{
firstName= grp.Key.firstName,
lastName = grp.Key.lastName,
}
);

Resources