query each month record in the table by linq - linq

I have a datatable named testable, it has two columns id(primary key, int) and time(datetime). I want to calculate the number of records of every specific month in the table. For example, there are 5 rows in the table,
Id datetime(d/m/y)
1 12/3/2011
2 15/3/2011
3 4/4/2011
4 1/8/2011
5 19/12/2011
How to write a Linq query to query out the record like this,
Id datetime count
1. 1/2011 0
2. 2/2011 0
3. 3/2011 2
4. 4/2011 1
5. 5/2011 0
6. 6/2011 0
7. 7/2011 0
8. 8/2011 1
9. 9/2011 0
10. 10/2011 0
11. 11/2011 0
12. 12/2011 1
I have written a query statement like this,
var query = from c in testtable.AsEnumerable()
group c by new
{
years = Convert.ToDateTime(c.Field<string>("Posted")).Year,
months = Convert.ToDateTime(c.Field<string>("Posted")).Month
}
into d
orderby d.Key.years,d.Key.months
select new
{
Date = String.Format("{0}/{1}",d.Key.months,d.Key.years),
Count = d.Count()
};
But it only queries out the month 3/4/8/12, it can’t query out other month records.
Anyone can help?

You need to generate a sequence of all dates and left join your existing query with that sequence.
var allMonths = Enumerable.Range(1, 12)
.Select(i => String.Format("{0}/{1}", i, "2011"));
var query = new[]
{
new{ Date= "3/2011" , Count = 2},
new{ Date= "4/2011" , Count = 1},
new{ Date= "8/2011" , Count = 1},
new{ Date= "12/2011", Count = 1},
};
var query2 = from month in allMonths
join date in query on month equals date.Date into g
from date in g.DefaultIfEmpty()
select new
{
Date = month,
Count = (date == null) ? 0 : date.Count
};
foreach (var q in query2)
{
Console.WriteLine(q);
}

Related

Linq groupby and global count (not count per group)

I have the following query:
var query = from incident in _dbContext.VehicleIncidents
join vehicle in _dbContext.Vehicles on incident.VehicleId equals vehicle.Id
where vehicle.EnterpriseId == enterpriseId
group incident by new {incident.ReportDate.Month, incident.ReportDate.Year}
into g1
orderby g1.Key.Year, g1.Key.Month
select new
{
Month = g1.Key.Month,
Year = g1.Key.Year,
Cost = g1.Sum(o => o.Cost)
};
It returns all the incidents aggregated by month and year. But I need the total number of incidents too. Not the incidents for every group, but the total count. The sum of the incidents of all groups. Can this be done in this query or is it better to just roll another query just to get the total global count?
I believe you could get the sum per group and then sum those. Something like
var query = from incident in _dbContext.VehicleIncidents
join vehicle in _dbContext.Vehicles on incident.VehicleId equals vehicle.Id
where vehicle.EnterpriseId == enterpriseId
group incident by new {incident.ReportDate.Month, incident.ReportDate.Year}
into g1
orderby g1.Key.Year, g1.Key.Month
select new
{
Month = g1.Key.Month,
Year = g1.Key.Year,
Cost = g1.Sum(o => o.Cost),
Count = g1.Count()
};
var total = queryResult.SUM(x=>x.count);
The other alternative I see is to join a sub query see Join Subquery result in Linq
something like
var subquery = from incident in _dbContext.VehicleIncidents
join vehicle in _dbContext.Vehicles on incident.VehicleId equals vehicle.Id
where vehicle.EnterpriseId == enterpriseId
into g1
select new
{
Total = g1.Count()
};
var query = from incident in _dbContext.VehicleIncidents
join vehicle in _dbContext.Vehicles on incident.VehicleId equals vehicle.Id
join sub in subquery on 1=1
where vehicle.EnterpriseId == enterpriseId
group incident by new {incident.ReportDate.Month, incident.ReportDate.Year}
into g1
orderby g1.Key.Year, g1.Key.Month
select new
{
Month = g1.Key.Month,
Year = g1.Key.Year,
Cost = g1.Sum(o => o.Cost),
Count = sub.total
};

Linq - Inner join with group with sum

I have 2 tables, first table if transactions
transaction table:
Id LoanId
1 100
The second table I have is a TransactionLeg table
transactionleg table:
ID TransactionId GLAmount
1 1 200
2 1 200
I would like to join the two on the TransactionId column, group by the loanID and sum the GLAmount
So it should produce the following:
LoanId TotalGlAmount
100 400
var investmentsWritten = from transaction in ctx.Transactions
join transactionleg in ctx.TransLegs on transaction.Id equals transactionleg.TransactionId
where
transaction.Class == Transaction.TransactionClasses.WriteOff &&
transaction.Created >= StartDate.Date && transaction.Created <= EndDate.Date
group transaction by transaction.LoanId
into g
select new { Id = g.Key, Value = _____ };
I was wondering what goes where the underline is, the value is transactionleg.GLAmount. I tried g.Sum(x => x.GLAmount) but GLAmount is not recognized, it is highlighted in red stating Cannot resolve symbol GLAmount
It is because GLAmount is in transactionleg not in transaction,
Modify your group by like this:
group new
{
transaction,
transactionleg
}
by new
{
transaction.LoanId
}
and now in Select:
select new
{
Id = g.Key,
Value = g.Sum(x=>x.transactionleg.GLAmount)
}

LINQ select row with the minimum date value

i have this linq query:
var query = from mpItem in MPay
where mpItem.EndDate > System.DateTime.Now.Date
group mpItem by mpItem.IdGroup into mpItemGrouped
let minEndDate = mpItemGrouped.Min(p => p.EndDate)
select new
{
Id = mpItemGrouped.Key,
EndDate = mpItemGrouped.Min(p => p.EndDate),
Name = mpItemGrouped.Min(p => p.IdGroupModel.GroupName),
Price = mpItemGrouped.Min(p => p.PaySumIndividual)
};
this query should select for each IdGroup the row with the minimum EndDate
this query is selecting the minimum EndDate with another row values.
Order group by EndDate in ascending order and select first item from group - that will be item with min date. Then use this item in select statement
var query = from MPayItem in MPay
where mpItem.EndDate > System.DateTime.Now.Date
group mpItem by mpItem.IdGroup into mpItemGrouped
let minItem = mpItemGrouped.OrderBy(p => p.EndDate).First()
select new
{
Id = mpItemGrouped.Key,
EndDate = minItem.EndDate,
Name = minItem.IdGroupModel.GroupName,
Price = minItem.PaySumIndividual
};

Linq query with two sub-queries that group by, one with an average, and one with a max

I have a parent table, parentTable which may or may not have children in childTable. I am looking to get average % complete of any given parent's children, and the MAX(due) (date) of the children where they exist. My SQL is this:
SELECT parentRecord_id, assigned_to,
(SELECT avg(complete)
FROM childTable
WHERE parent_id = parentRecord_id
and deleted IS NULL
GROUP BY parent_id),
(SELECT max(due)
FROM childTable
WHERE parent_id = parentRecord_id
and deleted IS NULL
GROUP BY parent_id
)
FROM parentTable s
WHERE s.deleted IS NULL and assigned_to IS NOT NULL
My result set gives me rows with either correct values for the average and max, or null. In this instance I have to do follow up processing so I could ignore the null values if I was doing a foreach through DataTable rows. However I am trying to do this in Linq and can't figure out how to avoid a System.InvalidOperationException where Linq is trying to cast null to a double. Here is what I've tried so far.
var query8 = from s in db.parentTable
where s.deleted == null
select new
{
ID = s.assigned_to,
Average =
((from t in db.childTable
where t.parent_id == s.strategy_id
group t by new { t.parent_id } into g
select new
{
a0 = g.Average(f0 => f0.complete )
}).FirstOrDefault().a0)
};
foreach (var itm in query8)
{
Console.WriteLine(String.Format("User id:{0}, Average: {1}", itm.ID, itm.Average));
}
Here's my question. How do I get the query to handle those returned rows where average complete or max due (date) are null?
You can either filter out the records where the values are null (by another condition) or if you want to include them do something like this:
a0 = g.Average(f0 => f0.complete.HasValue? f0.complete: 0 )
I would cast the list to nullable double before calling Average/Max like so:
var query8 =
from s in db.parentTable
where s.deleted == null
select new
{
ID = s.assigned_to,
Average =
from t in db.childTable
where t.parent_id == s.strategy_id
group t by t.parent_id into g
select g.Cast<double?>().Average(f0 => f0.complete)
};
Assuming complete is a Nullable, you should be able to do:
var query8 = from s in db.parentTable
where s.deleted == null
select new
{
ID = s.assigned_to,
Average =
((from t in db.childTable
where t.parent_id == s.strategy_id
&& s.complete.HasValue()
group t by new { t.parent_id } into g
select new
{
a0 = g.Average(f0 => f0.complete )
}).FirstOrDefault().a0)
};
Thanks to all who responded.
I was unable get around the null anonymous issue with the basic query as I had it, but adding a join to the childTable eliminated the nulls.
Another solution is to use a from x in g.DefaultIfEmpty clause.
var query8 =
from st in db.tableParent
select new { Ass = st.assigned_to ,
Avg =
(from ta in db.tableChild
group ta by ta.parent_id into g
from x in g.DefaultIfEmpty()
select g.Average((f0=>f0.complete))).FirstOrDefault()
};

Linq expression resquested

Let's say I have List of object containing these two records :
EmployeeId - Category - Amount
1 - T - 150
1 - D - 300
The result I want in the final is something looking lie this :
EmployeeId - TAmount - DAmount
1 - 150 - 300
How can I achive this using LINQ, I just don't see how to do this with a simple group by on my EmployeeId field ...
var employeeId = 1;
var query =
from row in table
group row by row.EmployeeId into g
where g.Key == employeeId
select new
{
EmployeeId = row.Key,
TAmount = g.SingleOrDefault(r => r.Categpry == "T"),
DAmount = g.SingleOrDefault(r => r.Categpry == "D"),
};

Resources