Linq syntax c# to select two field from table - c#

i am writing the following linq code in c#
var groupedData = from b in dt.AsEnumerable()
group b by b.Field<string>("TypeColor") into g
select new
{
Key = g.Key,
Value = g.Select(r => r.Field<int>("Price")),
Price = g.Select(r => r.Field<int>("Price"))
};
foreach (var g in groupedData)
{
string s = g.Key;
}
how can i select two or more field from the datatable and group the table with one field.
Can any body help me?
Here dt is a datatable which is binding from database

You need to aggregate the fields if you've grouped the rows(similar as in SQL):
var groupedData = from b in dt.AsEnumerable()
group b by b.Field<string>("TypeColor") into g
select new
{
Color = g.Key,
PriceSum = g.Sum(r => r.Field<int>("Price")),
FirstValue = g.First().Field<int>("Value")
};
foreach (var g in groupedData)
{
string color = g.Color;
Double priceSum = g.PriceSum;
int firstValue = g.FirstValue;
}

Related

How to group a datatable by month and count the rows that falls under that month

I'm trying to create a line chart using a datatable that has all the data that I need but I can't seem to group it successfully.
I need to group the datatable by month/year and count all the records that fall within each respective month/year.
I actually tried to extract the data and make the graph in excel. So it should look like this.
Ignore the quarters as those are auto generated by excel
Here's the code:
var chartResults = (from myrow in chartInstruction.Chart.AsEnumerable()
group myrow by new
{
series = myrow.Field<string>(chartInstruction.Series),
xaxis = myrow.Field<DateTime>(chartInstruction.Xaxis).ToShortDateString()
}
into g
select new
{
Field = g.Key,
Total = g.Count()
}).ToArray();
string[] xAxis = chartResults.Select(x => x.Field.xaxis).Distinct().OrderBy(x => x).ToArray();
string[] series = chartResults.Select(x => x.Field.series).Distinct().OrderBy(x => x).ToArray();
var seriesInfo = new List<SeriesInfo>();
foreach (string s in series)
{
var tmp = new List<double>();
foreach (string xx in xAxis)
{
var found = chartResults.FirstOrDefault(x => x.Field.xaxis == xx && x.Field.series == s);
tmp.Add(found?.Total ?? 0);
}
seriesInfo.Add(new SeriesInfo { Name = s, Series = tmp.ToArray() });
}

Group BY multiple using linq [duplicate]

This question already has answers here:
Group By Multiple Columns
(14 answers)
Closed 6 years ago.
Trying to group by multiple fileds but having issues with it. I want to group by period,productcode.
var ProductUsageSummary = from b in myProductUsage
group b by b.ProductCode into g
select new
{
Period = g.Key,
Code = g.Key,
Count = g.Count(),
TotalQty = g.Sum(n => n.Qty),
Price = g.Average(n => n.Price)
};
also tried
var ProductUsageSummary = from b in myProductUsage
group b by b.Period b.ProductCode into g
select new
{
Period = g.Key(n => n.period),
Code = g.Key,
Count = g.Count(),
TotalQty = g.Sum(n => n.Qty),
Price = g.Average(n => n.Price)
};
You could create an anonymouns object to to group on multiple columns (ex... new {prop1 prop2}) , and the grouped fields can be accessed by Key.PropertyName
Try this.
var ProductUsageSummary = from b in myProductUsage
group b by new { b.Period, b.ProductCode }into g
select new
{
Period= g.Key.Period,
Code = g.Key.ProductCode ,
Count = g.Count(),
TotalQty = g.Sum(n => n.Qty),
Price = g.Average(n => n.Price)
};
This is the correct syntax using Anonymous Types :
group b by new { b.ProductCode, b.Period } into g
Then in select:
g.Key.ProductCode and g.Key.Period
Full Query:
var ProductUsageSummary = from b in myProductUsage
group b by new { b.Period b.ProductCode } into g
select new
{
Period = g.Key.Period,
Code = g.Key.ProductCode,
Count = g.Count(),
TotalQty = g.Sum(n => n.Qty),
Price = g.Average(n => n.Price)
};

LINQ Query for GroupBy and Max in a Single Query

I have the following LINQ query but i want to modify it that I want to group by staffId and pick only those records whose ObservationDate is Max for each staffId.
from ob in db.TDTObservations.OfType<TDTSpeedObservation>()
select new
{
Id = ob.ID,
AcademicYearId = ob.Teachers.FirstOrDefault().Classes.FirstOrDefault().AcademicYearID,
observationDate = ob.ObservationDate,
schoolId = ob.Teachers.FirstOrDefault().Classes.FirstOrDefault().SchoolID,
staffId=ob.Teachers.FirstOrDefault().ID
};
var observations =
from ob in db.TDTObservations.OfType<TDTSpeedObservation>()
select new {
Id = ob.ID,
AcademicYearId = ob.Teachers.FirstOrDefault().Classes.FirstOrDefault().AcademicYearID,
observationDate = ob.ObservationDate,
schoolId = ob.Teachers.FirstOrDefault().Classes.FirstOrDefault().SchoolID,
staffId=ob.Teachers.FirstOrDefault().ID
};
var result = from o in observations
group o by o.staffId into g
select g.OrderByDescending(x => x.observationDate).First();
what about this: hereby you first group your entries (Teachers) by their ID together and then from each group (grp) you pick that one with the latest ObservationDate
var observations = from d in db.TDTObservations.OfType<TDTSpeedObservation>()
group d by d.Teachers.FirstOrDefault().ID into grp
select grp.OrderByDescending(g => g.ObservationDate).FirstOrDefault();

How to find same values in a list column and concatenating strings on the other rows for the same column value

I have a List with 2 columns with the following structure:
50 process:3333
50 phone:xxxx
51 process:2222
51 phone:yyyy
I need to build a new list based on that first one with this structure:
50 process:3333,phone:xxxx
51 process:2222,phone:yyyy
Does List have any method to find from one column a same value and concatenate the string on second column.
Or I have to find a way to do it manually using a foreach or a while statement?
Assuming a simple struct like...
public struct Proc
{
public int ID { get; set; }
public string Value { get; set; }
}
with your sample data:
var procList = new List<Proc>() {
new Proc{ID=50,Value="process:3333"},new Proc{ID=50,Value="phone:xxxx"},
new Proc{ID=51,Value="process:2222"},new Proc{ID=51,Value="phone:yyyy"},
};
You can use Enumerable.GroupBy and String.Join:
var procIdGroupList = procList
.GroupBy(p => p.ID)
.Select(g => new Proc
{
ID = g.Key,
Value = string.Join(",", g.Select(p => p.Value))
}).ToList();
DEMO
Found a workaround for that:
//Recupera valores dos indices para o tipo de documento
List<Gedi.Models.OperacoesModel.imports> valuesList = new List<Gedi.Models.OperacoesModel.imports>();
var valuesListObj = from a in context.sistema_Documentos
join b in context.sistema_Indexacao on a.id equals b.idDocumento
join c in context.sistema_Indexes on b.idIndice equals c.id
where a.ativo == 1
select new
{
id = a.id,
values = c.idName + ":" + b.valor
};
var çist = (from x in valuesListObj.AsEnumerable()
select new Gedi.Models.OperacoesModel.imports
{
id = x.id,
values = x.values
}).ToList();
var importList = çist.GroupBy(p => p.id).Select(g => new Gedi.Models.OperacoesModel.imports
{
id = g.Key,
values = string.Join(",", g.Select(p => p.values))
}).ToList();

How can I filter results of one LINQ query based on another?

Given the following:
DP_DatabaseTableAdapters.EmployeeTableAdapter employeetableAdapter = new DP_DatabaseTableAdapters.EmployeeTableAdapter();
DP_Database.EmployeeDataTable employeeTable = employeetableAdapter.GetData();
var leadEmployees = from e in employeeTable
where e.IsLead == true
select e;
DP_DatabaseTableAdapters.LaborTicketTableAdapter tableAdapter = new DP_DatabaseTableAdapters.LaborTicketTableAdapter();
DP_Database.LaborTicketDataTable table = tableAdapter.GetDataByDate(date.ToString("MM/dd/yyyy"));
var totHours = from l in table
join e in leadEmployees on l.EmployeeID equals e.EmployeeID
group l by l.EmployeeID into g
orderby g.Key
select new
{
EmployeeID = g.Key,
HoursWorked = g.Sum(s => s.HoursWorked)
};
Total hours correctly filters the results based on the leadEmployee's list of people who have the IsLead bit set to true.
I would like to know how to do this with a where clause, I have attempd to use leadEmployees.Contanis but it wants a whole EmployeeRow...
How can I add what looks to be part of an IN clause to a where filter to replace the join?
var totHours = from l in table
where ??????
group l by l.EmployeeID into g
orderby g.Key
select new
{
EmployeeID = g.Key,
HoursWorked = g.Sum(s => s.HoursWorked)
};
The contains will only want a whole EmployeeRow if you are selecting whole employee roles. You can either:
leadEmployees.Select(e => e.id).contains
OR
leadEmployees.Count(e => e.id == l.id) > 0
Both will work. (Excuse slightly rushed lack of consideration for syntax accuracies).
This should work:
var leadEmployees = from e in employeeTable
where e.IsLead == true
select e.EmployeeID;
var totHours = from l in table
where leadEmployees.Contains(l.EmployeeID)
group l by l.EmployeeID into g
orderby g.Key
select new
{
EmployeeID = g.Key,
HoursWorked = g.Sum(s => s.HoursWorked)
};

Categories

Resources