EF Query Help - Grouping and Sub queries - c#

I have data table (DOCs, which is the DBSet in my context) with below data
ID Code Rev
1 A1 1
2 A1 2
3 A1 3
4 A3 1
5 A2 1
6 A2 2
I need to select the records which has a records for each Code which has the highest Rev. My expected result is
ID Code Rev
3 A1 3
6 A2 2
4 A3 1
The ID column is the PK of the table and Code+Rev is unique.
Note: There are other fields in the table which i need to get for the result. Ideal would be to get a iqueryable (Doc is the model class), i was think of selecting the ID within an inner query and then use that to get the iqueryable of docs.
Thanks in Advance

Try this:
var res = from r in DOCs
where (from c in DOCs
group c by c.Code into g
select new {
localCode = g.Key,
localRev = g.Max(t => t.Rev)
}).Any(x => x.localCode == r.Code && x.localRev == r.Rev)
select r;
res is IQueryable.

Related

Need linq query to obtain specific result set

If any one can help here to prepare this linq query.
Below is the table data:
category question answer user
a1 q1 3 u1
a1 q1 5 u2
a1 q2 3 u2
a2 q3 3 u3
a2 q3 2 u4
a3 q4 9 u3
a3 q5 8 u7
a3 q5 2 u9
I need result as below:
group by Category, Question, Result (group with three condition as below).
so, for each category, each question, need to group the result in three form(group by answer (<=3) and one group, answer = 5 and third group answer=8 OR 7 OR 9),
category name Question TotalCount Ans(<=3) Ans(5) Ans(7 or 8 or 9)
a1 q1 2 1 1 0
a1 q2 1 1 0 0
a2 q3 1 1 0 0
.....
I tried by using below query in SQL (it is not perfect query as i need column for result group instead of record).
SELECT
Category, Question,
Count(Ans),
CASE
WHEN Ans = 9 OR Ans = 8 OR ans=7 THEN '9 or 8 or 7'
WHEN Ans = 5 THEN '5'
WHEN Ans <= 3 THEN '<=3'
END as 'ResultGroup'
FROM
SurveyQuestions
GROUP BY
Category, Question, Ans
ORDER BY
Question
Please guide me how to get the result as shown above. I need LINQ query to obtain this result.
thanks
You don't need to group it by answer. Instead filter and count on the answer something like below:
from t in db.Table
group t by new {t.Category, t.Question} into g
order by g.Category
select new
{
CategoryName = t.FirstOrDefault().Category, //might be required to handle null here
Question = t.FirstOrDefault().Question, //might be required to handle null here
TotalCount = t.Count(),
AnsLessEqual3 = t.Where(d => d.Answer<=3).Count(),
Ans5 = t.Where(d => d.Answer = 5).Count(),
Ans789 = t.Where(d => d.Answer = 7 || d.Answer = 8 || d.Answer = 9).Count()
}
Although above query is not tested but I believe it would give you quick start for moving forward.

Grouping records that haven't groups values

Please consider this records:
Id Week Value
-----------------------------
1 1 1000
2 1 1200
3 2 800
4 3 1800
5 3 1100
6 3 1000
I want to group records for 4 weeks but we haven't record for week 4.For Example:
Week Count
---------------------
1 2
2 1
3 3
4 0
How I can do this with linq?
Thanks
First you need an array of weeks then this query might help
var weeks = new List<int>{1,2,3,4}
var q = from w in weeks
join rw in (
from r in table
group r by r.Week into g
select new {week = g.Key, count = g.Count()}) on w equals rw.week into p
from x2 in p.DefaultIfEmpty()
select new {w, count = (x2 != null ? x2.count : 0)};
online result in .net fiddle
You can try
var result = Enumerable.Range(1, 4)
.GroupJoin(table,
week => week,
record => record.Week,
(week, records) => new { Week = week, Count = records.Count() });
As suggested by jessehouwing, the Enumerable.Range will return the possible week numbers to be used as left outer keys within the join.
GroupJoin will then accept as parameters
A lambda/delegate/method that returns the left outer key
A lambda/delegate/method that extracts the right key from your table.
A lambda/delegate/method that builds an item of the result.
Regards,
Daniele.

Linq Query for EAV design table

I had a situation to use EAV design tables and I am new to this design,I am struck with a select query. Below is my query structure and data.
TABLE1:
Id KeyName
1 Name
2 Age
TABLE2:
ID TABLE1_ID VALUE
1 1 ABC
2 2 12
3 1 CDF
4 2 14
5 1 XYZ
6 2 13
7 1 CSF
8 2 10
EXPECTED OUTPUT: Get all the values which are greater than 12 AND Value contains "C".
i.e.,
Table2_ID Result Table1_KeyName
1 ABC Name
2 12 Age
3 CDF Name
4 14 Age
Options I tried are:
Var temp = (from c in Table2
where c.Value > 12 && c.Table1.KeyName.Contains("C")
Select new
{
ID = c.ID,
Result = C.Value
});
the above query didn't returned any result, as filters(in where clause) are across rows. I even tried "OR" condition in where clause, it returns me everything. Please do help me.
Your query is wrong, did you type it in here or copy and paste it from your work?
Do you have this table setup in an ORM such as Entity Framework? So that there is a relationship setup between table1 and table2, so you don't have to 'join' them?
To be more 'correct' it should be...
Var temp = (from c in Table2
where c.Value > 12 && c.Table1.Name.Contains("C")
Select new
{
ID = c.ID,
Name = c.Table1.Name,
Value = c.Value
});
Or if the relationship isn't in an ORM your using explicitly specify the join as follows:
Var temp = (from c in Table2
join c1 in Table1 on c.Table1_ID equals c1.Id
where c.Value > 12 && c.Table1.Name.Contains("C")
Select new
{
ID = c.ID,
Name = c.Table1.Name,
Value = c.Value
});
Edit: then it should be an OR, not AND
Var temp = (from c in Table2
where c.Value > 12 || c.Value.Contains("C")
Select new
{
ID = c.ID,
Result = c.Value,
KeyName = c.Table1.Name
});

How to return value from 2 tables in one linq query

please consider this table:
PK_Id Number Year Month Value
-------------------------------------------------------------------------
1 1 2000 5 100000
410 4 2000 6 10000
8888 1 2001 5 100
I Id=8888 and now I want to first select record with Id=8888 and second select previos year of that record*(I mean Id=1)*. How I can do this with linq and one query.
basically we have some queries that first it should find a value from a table (that may be not PK) and find Corresponding records in another tables. How I can do this with linq and one reference to database.
thanks
from a in Record
where a.PK_Id == 8888
from b in Record
where b.Number == a.Number && b.Year == a.Year - 1
select new { Current = a, Previous = b }
or
Record
.Where(a => a.PK_Id == 888)
.SelectMany(a =>
Record
.Where(b => b.Number == a.Number && b.Year == a.Year - 1)
.Select(b => new { Current = a, Previous = b })
If I understand your question right, then you need to filter the data of one table and join two tables.
You can join the tables and filter your data
var query = from c in Table1
join o in Table2 on c.Col1 equals o.Col2
where o.Col3 == "x"
select c;
or you can filter your data from one table and then join the tables (result will be the same)
var query = from c in Table1.Where(item => item.Col3 == "x")
join o in Table2 on c.Col1 equals o.Col2
select c;

Populating an ObservableCollection of ObservableCollection, delimited by two database columns

My database is as follows :
ID Date Number NumberIWishToRecord
What I wish to do is use a Linq-to-SQL query to populate an ObservableCollection<ObservableCollection<CustomClass>>.
What I want is select only the rows were Number == a given parameter.
ID refers to a person, what I want to do is get all the information about a person and store it in an ObservableCollection, so I will have an ObservableCollection<CustomClass>, with each CustomClass holding information about only one row, and each ObservableCollection<CustomClass> holding information about only one person (recorded on different days).
I then wish to select an ObservableCollection of the ObservableCollection<CustomClass> which will hold information on all people!
So, some sample data :
ID Date Number NumberIWishToRecord
1 27-06-2012 0.1933 25
1 28-06-2012 0.1933 27
1 29-06-2012 0.1933 29
2 14-06-2012 0.1933 412
2 15-06-2012 0.1741 321
So when I run my method, I want to return only the Numbers of the given parameter, in my case I will choose 0.1933.
I then want both rows where ID = 1 to be saved in an ObservableCollection<CustomClass>, and the single row where ID == 2 to be saved in another ObservableCollection<CustomClass>. Then, both of these ObservableCollections will be held in their own ObservableCollection! To illustrate :
ObservableCollection<ObservableCollection<CustomClass>>
ObservableCollection<CustomClass>
1 27-06-2012 0.1933 25
1 28-06-2012 0.1933 27
1 29-06-2012 0.1933 29
ObservableCollection<CustomClass>
2 14-06-2012 0.1933 412
How would I write a query in linq to sql that would do this ?
I'll just write a standard query syntax Linq expression to achieve this, you adapt it for your tables.
var rowsById = new ObservableCollection<ObservableCollection<row>>(
from r in _rows
where r.number == 1.2
group r by r.ID into rowIdGroup
select new ObservableCollection<row>(rowIdGroup));
If you need to convert data from the row into the CustomClass:
var rowsById = new ObservableCollection<ObservableCollection<CustomClass>>(
from r in _rows
where r.number == 1.2
group r by r.ID into rowIdGroup
select new ObservableCollection<CustomClass>(
rowIdGroup.Select(r => new CustomClass
{
ID = r.ID,
Number = r.number // add more
})));
Or if you prefer query syntax in all the expression:
var rowsById = new ObservableCollection<ObservableCollection<CustomClass>>(
from r in _rows
where r.number == 1.2
group r by r.ID into rowIdGroup
select new ObservableCollection<CustomClass>(
from gr in rowIdGroup select new CustomClass
{
ID = gr.ID,
Number = gr.number
}));

Categories