Grouping records that haven't groups values - c#

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.

Related

Sum duplicated objects in an array

I have an unsorted array of objects with CustomerId, ProductId and Count (all ints)
I want to combine records where CustomerId and ProductId match, summing the count.
for example:
CId PId Cnt
1 100 5
1 100 1
2 100 7
Desired output:
CId PId Cnt
1 100 6
2 100 7
As you can see for the two records for CId 1 & PId 100 have been merged and the count has been summed.
Can this be done with LINQ?
I know it could done with loops but I'm hoping for a more elegant way
Here I have assumed that the class name is Item:
var result = array.GroupBy(x => new { x.CId, x.PId })
.Select(g => new Item { CId = g.Key.CId, PId = g.Key.PId, Cnt = g.Sum(x => x.Cnt) });
Here is a Live Demo

Linq to sql calculating a percentage of a group of items in query

New to Linq to SQL and novice in SQL. First post so please be gentle.
I have something similar to the following table I am querying into a dataGridView based on a date range in C#.
HeatNumber ChargeNumber Weight DOB
1 1 500 8/26/15
1 2 3500 8/26/15
1 3 2200 8/26/15
2 1 2000 8/27/15
2 2 1100 8/27/15
var query = from SU in dct.GetTable<ScrapInCharge>()
where ((SU.DOB >= dateTimePicker2.Value.Date) &&
(SU.DOB <= dateTimePicker1.Value.Date))
orderby SU.HeatNumber descending
select SU;
scrapInChargeBindingSource.DataSource = query;
I need to add a column that shows the percentage of the total HeatNumber weight that each ChargeNumber makes up. I did figure how to get the total weight of each heat by HeatNumber.
var TotalHeatWgt = from a in dct.ScrapInCharges
where ((a.DOB >= dateTimePicker2.Value.Date) &&
(a.DOB <= dateTimePicker1.Value.Date))
group a.Weight by a.HeatNumber
into b
select new { HeatNumber = b.Key, TotalWgt = b.Sum() };
I am currently stuck on how to combine this into a single C# query inserting a % of Heat column after the weight column. Can this be done or would I need to add an unbound column to the dataGridView % of Heat and iterate over the rows using my return values of the TotalHeatWgt query?
Simple attempt:
var results = data.Select(d => new {
d.HeatNumber,
d.ChargeNumber,
d.Weight,
Percent = 100.0 * d.Weight / data.Where(dd => dd.HeatNumber == d.HeatNumber).Sum(dd => dd.Weight)
});
or
from row in data
select new {
row.HeatNumber,
row.ChargeNumber,
row.Weight,
Percent = 100.0 * row.Weight / (from innerRow in data
where innerRow.HeatNumber == row.HeatNumber
select innerRow.Weight
).Sum()
};
The one below will be more performant (at least in memory, I'm not sure if it'll be better in SQL):
var results = data.GroupBy (d => d.HeatNumber)
.SelectMany (grp => grp.Select(row => new {
row.HeatNumber,
row.ChargeNumber,
row.Weight,
Percent = 100.0 * row.Weight / grp.Sum(dd => dd.Weight)
})
);
And with query syntax:
from row in data
group row by row.HeatNumber into grp
from innerRow in grp
select new {
innerRow.HeatNumber,
innerRow.ChargeNumber,
innerRow.Weight,
Percent = 100.0 * innerRow.Weight / grp.Sum(dd => dd.Weight)
};
They both print this result:
HeatNumber ChargeNumber Weight Percent
1 1 500 8.06451612903226
1 2 3500 56.4516129032258
1 3 2200 35.4838709677419
2 1 2000 64.5161290322581
2 2 1100 35.4838709677419
Is that what you're after? I've omitted the filtering by date just for simplicity, since the actual problem comes after that

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.

EF Query Help - Grouping and Sub queries

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.

SQL Show records that meet a provided criteria

I have the following table
CamId RegNumber DateSeen
5 G1234B 18/02/2014 11:54
3 G1234B 18/02/2014 11:51
5 G11854 18/02/2014 11:50
3 G11854 18/02/2014 11:49
3 G24581 18/02/2014 11:48
5 G24581 18/02/2014 11:47
I would like to retrieve all records with CamId 3 that do not have a later entry in CamId 5 based on the dateseen entry on CamId 3 for that particular reg number.
From the sampe data table above the system should return just one number plate G24581 as it has no later entries in CamId 5.
One method you can employ is to join onto the table twice so that in one table you have the values where CamID is 3 and the other is 5. Then you would want to get all records from the first table that do no have a record in the second table.
Select A.* from Table A
LEFT JOIN ( Select * from Table ) B on A.RegNumber = B.RegNumber AND A.CamID = 3 and B.CamID = 5 AND A.DateSeen <= B.DateSeen
WHERE B.CamID IS NULL
Try this:
var query = from r1 in db.Regs
where r1.CamId == 3 &&
!db.Regs.Any(r2 => r2.CamId==5 && r2.DateSeen>r1.DateSeen && r2.RegNumber==r1.RegNumber)
select r1;

Categories