Nested Select MySQL statements to LINQ - c#

I'm trying to convert the following MySQL statement in to LINQ query format
SELECT * FROM table1 WHERE table1.id IN (SELECT c_id FROM table2 WHERE a_id IN (1, 49) GROUP BY c_id HAVING COUNT(*) = 2) ORDER BY name
Got as far as this, but I'm drawing a blank on how to handle the IN and 2nd SELECT statement
myItems = from c in table1
let id = c.id
where ????
orderby c.name
select c;
Would appreciate some guidance with this please

Try this:
var ids=new[]{1,49};
var innerquery=table2.Where(e=>ids.Contains(e.a_id))
.GroupBy(e=>e.c_id)
.Where(g=>g.Count()==2)
.Select(g=>g.Key);
var myItems = from c in table1
where innerquery.Contains(c.id)
orderby c.name
select c;
First define your inner query,after the group by you will get a collection of IGrouping<TKey, TElement>> that represent a collection of objects that have a common key, filter the groups choosing only those where count==2, and select the keys of those groups. The second part is really easy to understand. I split the process in two queries to do it more readable, but you can merge both query in one.

Related

How to convert Group By SQL to LINQ?

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 };

SQL query distinct issue

I have written the below query to list all the rows in table [HRSurvey]
which empid is only present in empsurveyselection. Both table have empid columns.
But i am not able to get the proper results because there
might be multiple empid for same surveyid in empsurveyselection table.
But this query works fine when there is only one empid for each surveyid in empsurveyselection table.
Could you please rewrite the query to list the all the rows in the table HRSurvey where the empid are there in empsurveyselection ?
SELECT hrs.*
FROM [HRSurvey] hrs
Left Join [HRSurveyEmployee] hse
ON hse.EmpID = hrs.EmpID
LEFT Join Surveys s
ON s.surveyid = hse.surveyid
WHERE hrs.empid IN (
SELECT empid FROM [HRSurveyEmployee] where surveyid = s.surveyid
) and sempid
in ( select DISTINCT empid FROM empsurveyselection WHERE deptid=9 and surveyid = s.surveyid)
You can write as:
SELECT hrs.col1, -- Worst Practice to use * in production code to pull data
hrs.col12 -- Use explicit column names instead
FROM [HRSurvey] hrs
INNER JOIN [HRSurveyEmployee] hse ON hse.EmpID = hrs.EmpID
INNER JOIN [Surveys] s ON s.surveyid = hse.surveyid
INNER JOIN [empsurveyselection]ess ON ess.deptid=9
AND ess.surveyid = s.surveyid AND hrs.sempid = ess.empid
Please try with the below query....
select a.*
from HRSurvey a
where empid exists (select 1
from empsurveyselection b
where a.Empid = b.Empid)
Thanks for the help! Actually issue was not with the query. Issue was with the data and i fixed it.

Getting most recent record based on datetime column SQL

I am trying to select the most recent record. Right now it is returning all records. Which makes since, because I have not put in a filter to get most recent, I am unsure of how to do that. Here is my code:
select
c.my_Name, a.my_Num, d.myBrand, a.order_bill, a.myDate
from
[table1] a
left join
[table2] b on a.[myCode] = b.[myCode]
left join
[table3] c on c.myTag = b.myTag
left join
[table4] d on a.[myHash] = d.[myHash]
where
c.[myName] = 'test name'
I am wanting to get most recent record from the table, I am guessing the most efficient way is to get most recent a.myDate.
I'd write
SELECT TOP 1
c.my_Name, a.my_Num, d.myBrand, a.order_bill, CONVERT(char(10), a.myDate,126)
FROM [table1] a
LEFT JOIN [table2] b on a.[myCode] = b.[myCode]
LEFT JOIN [table3] c on c.myTag=b.myTag
LEFT JOIN [table4] d on a.[myHash] = d.[myHash]
WHERE c.[myName] = 'test name'
ORDER BY a.myDate DESC
Something like this might help
select c.my_Name, a.my_Num, d.myBrand, a.order_bill, MAX(a.myDate)
from [table1] a
left join [table2] b on a.[myCode] = b.[myCode]
left join [table3] c on c.myTag=b.myTag
left join [table4] d on a.[myHash] = d.[myHash]
where c.[myName] = 'test name'
group by c.my_Name, a.my_Num, d.myBrand, a.order_bill
order by a.myDate DESC
This will grab distinct records with the greatest (most recent) a.myDate, grouped by your other elements.
Be aware of duplicates. Use your duplicate criteria keys in the select statement, or whatever elements you absolutely need to be distinct.

Select only defined column in LINQ

I am writing a simple LINQ query. Table structure is defined below:
Table A
Id int,
VName varchar2(20),
VAddress varchar2(200)
Table B
Id int,
NName varchar2(20),
NAddress varchar2(200)
LINQ Query
from c in A
join x in B on c.Id equals x.Id
order by A.Id
select New{
c.Id,
x.NName
}
Then SQL Generate as
select Filter1.Id,Filter1.NName from(
Select Extend1.Id,Extend1.VName,Extend1.VAddress,
Extend2.Id as Id1,Extend2.NName,Extend2.NAddress
from A as Extend1 Inner Join B as Extend2 on Extend1.Id=Extend2.ID)
as Filter1
MY Problem: I don't want select many columns in SubQuery.
If you're really worried about performance, then just use plain SQL... it's just about always faster than Linq (in my personal experience). Also, you can try using this Linq to execute your SQL:
IEnumerable<YourDataType> result = DataContext.ExecuteQuery<YourDataType>(SqlString);
You can find out more from the DataContext.ExecuteQuery<TResult> Method (String, Object\[\]) page at MSDN. Please note that this page relates to a different overload of this method, but it has examples in it.

LINQ Group by and having where clause

Below is the SQL Query I am trying to translate
SELECT dbo.Contracts.Supplier
FROM dbo.Contracts INNER JOIN dbo.Products ON dbo.Contracts.Product = dbo.Products.Product
where dbo.Products.ProductGroup='Crude'
GROUP BY dbo.Contracts.Supplier
Am I doing something wrong because I do not get same results with the following LINQ
var result = from c in context.Contracts
join p in context.Products on c.Product equals p.Product1
where p.Product1.Equals("Crude")
group c by c.Supplier into g
select new { supplier = g.Key };
It is generating a weird statement
SELECT
1 AS [C1],
[Distinct1].[Supplier] AS [Supplier]
FROM ( SELECT DISTINCT
[Extent1].[Supplier] AS [Supplier]
FROM [dbo].[Contracts] AS [Extent1]
WHERE N'Crude' = [Extent1].[Product]
) AS [Distinct1]
Using distinct would work but to get same results, LINQ should be generating a statement like so (it's like it is ignoring the join):
SELECT distinct dbo.Contracts.Supplier
FROM dbo.Contracts INNER JOIN dbo.Products ON dbo.Contracts.Product = dbo.Products.Product
where dbo.Products.ProductGroup='Crude'
I'm assuming that you are using 'EntityFramework' or 'Linq To SQL'. If so, you should be able to use navigation properties to navigate to product and filter invalit results out. This way your query might look something like this:
var result = (from c in context.Contracts
where c.Products.Any(p => p.ProductGroup == "Crude")
select c.Supplier).Distinct();
It will automatically convert into correct query (in this case possibly without join even, just using Exists sql keyword) and return distinct suppliers. This is if I understand your objective correctly - you want to obtain all suppliers assigned to contracts that contain product from 'Crude' product group.
Basically you should try to avoid using joins from linq to sql or linq to entities as much as possible when you can use navigation properties. System will probably be better at converting them into specific sql.

Categories