Want to sum fee in query month wise - c#

var TotalFee = (from item in _dbEntities.MonthlyFees
where item.Year == DateTime.Now.Year &&
item.FeeStatus == true
select item).GroupBy(x =>x.MonthID);//.AsEnumerable().Sum(x => int.Parse(x));
I want to sum Column "Fee" which is nvarchar type and group it by MonthID

Just look to this example
var feesDictionary = _dbEntities.MonthlyFees
.Where(x => x.Year.Equals(DateTime.Now.Year) && x.FeeStatus)
.GroupBy(x => x.MonthID)
.ToDictionary(x => x.Key, x => x.Sum(y => Convert.ToDouble(y.Fee)));
The keys are identifiers of months and values - sums of fee for appropriate month.

Related

How to select last hour and groupby minute?

I want to select data from SQL database using EF, select the last hour and then group by minute.
var result = _dbContext.views
.Where(x => x.Id == id && x.Created > DateTime.UtcNow.AddHours(-1))
.OrderBy(x => x.Created)
.GroupBy(x=> x.Created.Where({Range is 1 minute}));
DateTime instance has a Minute property which is an int so you can use the x.Created.Minute for grouping:
var result = _dbContext.views
.Where(x => x.Id == id && x.Created > DateTime.UtcNow.AddHours(-1))
.OrderBy(x => x.Created)
.GroupBy(x=> x.Created.Minute}));

Linq query to get the list filtered by max value in one query

Could you help me to improve this code?
var orderNo = "1234";
var maxValue = MyTable.Where(x => x.OrderNo == orderNo )
.OrderByDescending(x => x.Filename)
.Select(x => x.Filename)
.FirstOrDefault();
var list = (from x in MyTable
where x.OrderNo == orderNo && x.Filename == maxValue
select x).Distinct();
list.Dump();
Is it possible to improve these 2 Linq queries into 1 and avoiding query 2 times my database. Something like:
var list = (from x in MyTable
where x.OrderNo == orderNo && MaxValue(x.Filename)
select x)
.Distinct();
You could use GroupBy:
var list = MyTable
.Where(x => x.OrderNo == "1234") // or var1
.GroupBy(x => x.Filename)
.OrderByDescending(g => g.Key)
.First()
.Distinct();
Try
var list = (
from x in MyTable
where x.OrderNo == var1 &&
x.Filename == MyTable.Where(x => (x.OrderNo == "1234")).Max(p => p.Filename)
select x
).Distinct();
Why not just:
MyTable.Where(x => x.OrderNo == "1234")
.Max(x => x.Filename);
You will get all the records that have the maximal filename.

c# lambda reading each row with GROUP BY and SUM

This is the working query i was using in my management studio.
SELECT TOP 5 productCode, SUM(productSales) AS sales
FROM sellingLog
WHERE (salesYear = '2014')
GROUP BY productCode
ORDER BY sales DESC
I want to convert the query above into lambda, but i can't seems to make it works. the lambda still lacks of order by and select the productCode
var topProducts = sellingLog
.Where(s => s.salesYear == 2014)
.GroupBy(u => u.productCode)
.Select(b => b.Sum(u => u.productSales)).Take(5)
.ToList();
foreach(var v in topProduct)
{
//reading 'productCode' and 'sales' from each row
}
var topProducts = sellingLog
.Where(s => s.salesYear == 2014)
.GroupBy(u => u.productCode)
.Select(g => new { productCode = g.Key, sales = g.Sum(u => u.productSales) })
.OrderByDescending(x => x.productCode)
.Take(5)
.ToList();
You can use the .Key with group by to get productCode
var topProducts = sellingLog
.Where(s => s.salesYear == 2014)
.GroupBy(u => u.productCode)
.Select(b => new {u.Key, b.Sum(u => u.productSales)}).Take(5)
.OrderByDescending(b=>b.Sales)
.ToList();

Sum values in datatable using linq based on conditions

I'm having a datatable like mentioned below.
ID Percentage
1 50
1 30
2 0
2 100
Result:
ID Percentage
1 80
2 100
I tried this and it doesn't work
var n = dt.AsEnumerable()
.Where(r => (int)r["ID"] != "0" || (int)r["ID"] != "100")
.Sum(r => (int)r["Percentage"]);
I'm new to linq and pls provide some suggestions.
Now I need to sum the percentage for each ID and the percentage for each ID should be 0 or 100 percentage.
If any one of the ID in table doesn't have 0 or 100 I need to alert. Pls suggest me how I can do this in linq and I think its the best way.
var result = from row in dt.AsEnumerable()
group row by row["ID"]
into g
select new
{
ID = g.Key,
Sum = g.Sum(x => int.Parse(x["Percentage"].ToString()))
};
var errorItems = result.Where(x => x.Sum != 100 && x.Sum != 0);
if (errorItems.Any())
{
var ids = errorItems.Select(x => x.ID);
string msg = string.Format("ID(s): [{0}] don't meet condition.", string.Join(",", ids));
MessageBox.Show(msg);
}
You are not trying get the sum of "Percentage" for the whole table so directly doing a sum on it wont give you the desired result.
You're trying to find the sum of the percentage for each ID value so you need to group it by ID.
That's what GroupBy(g => g.Field<int>("ID")) does. Then you take the group(g), and for each group, you sum the "Percentage" Column of the members i.e.. .Select(g => g.Sum(p => p.Field<int>("Percentage")))
Here is the complete code.
dt.AsEnumerable().Where(r => r.Field<int>("ID") == 0 || r.Field<int>("ID") == 100).GroupBy(g => g.Field<int>("ID")).Select(g => g.Sum(p => p.Field<int>("Percentage")));
to put an alert message you can use Any instead of the where to check for the presence of the values
if(dt.AsEnumerable().Any(r => r.Field<int>("ID") != 0 && r.Field<int>("ID") != 100)
{
Console.WriteLine("Alert");
}
I guess that you want a new DataTable with the same columns as the first but with grouped percentage by ID? Then have a look at GroupBy and Sum:
var groupQuery = dt.AsEnumerable()
.Select(r => new { ID = r.Field<int>("ID"), Percentage = r.Field<int>("Percentage") })
.Where(x => x.ID != 0 && x.ID != 100)
.GroupBy(x => x.ID);
DataTable groupingTable = dt.Clone(); // empty, same columns
foreach(var grp in groupQuery)
groupingTable.Rows.Add(grp.Key, grp.Sum(x => x.Percentage));
This presumes that the type of the columns is actually int. If they are strings the best way is to change it to int, if you can't do that you have to use int.Parse.
For example:
ID = int.Parse(r.Field<int>("ID"))`
Update: Although it's not clear what you want if i reread your qustion, especially:
If any one of the ID in table doesn't have 0 or 100 I need to alert
You could use this to get all ID-groups without 0 or 100 percentage:
var without0Or100Perc = dt.AsEnumerable()
.Select(r => new { ID = r.Field<int>("ID"), Percentage = r.Field<int>("Percentage") })
.GroupBy(x => x.ID)
.Where(g => !g.Any(x => x.Percentage == 0 || x.Percentage == 100));
Now you can use Any, FirstOrDefault or a foreach loop to consume this query, so one of following approches:
bool anyWithout0Or100Perc = without0Or100Perc.Any();
var firstWithout0Or100Perc = without0Or100Perc.FirstOrDefault();
anyWithout0Or100Perc = firstWithout0Or100Perc != null;
foreach (var grp in without0Or100Perc)
{
Console.WriteLine("ID: {0} Percentages:{1}",
grp.Key,
String.Join(",", grp.Select(x => x.Percentage)));
}

How to write the following query in LINQ

I have a sql query and would like to convert it into linq
SELECT CAST([Date] AS DATE),
COUNT([ID]) AS 'Amount of Systems'
FROM [DemoDB].[dbo].[Servers]
WHERE [ServerID] IN ('ServerX') AND [Type] = 'Complete'
GROUP BY CAST([Date] AS DATE)
ORDER BY CAST([Date] AS DATE)
this will return the result as follows
What I have tried
//fromDP and toDP are the names of the Datepicker's
var query = (this.db.Servers
.Where(x => x.Date >= fromDP.SelectedDate.Value &&
x.Date <= toDP.SelectedDate.Value));
var query_Success = query.Count(p => p.Type == "Complete"
&& (p.ServerID == "ServerX"));
and I have the result as Count on the whole ( for example, if I select from from April 1st to April 15th , the result is the sum of all "complete"), but I need count for each day in this selected range. the result I will bind to the column chart.
how to proceed ?
If I understood correctly the author wants to use only the date without the time. To do this with EF we can use the method EntityFunctions.TruncateTime for trimming the time portion. I will build on #steaks answer:
db.Servers.Where(s => s.ServerId == "ServerX" && s.Type == "Complete")
.GroupBy(s => EntityFunctions.TruncateTime(s.Date))
.OrderBy(s => s.Key)
.Select(g => new {Date = g.Key, AmountOfSystems = g.Count()});
this.db.Servers.Where(s => s.ServerId == "ServerX" && s.Type == "Complete")
.GroupBy(s => s.Date)
.OrderBy(s => s.Key)
.Select(g => new { Date = g.Key, AmountOfSystems = g.Count() });
Change the Where clause to read
Where(s => s.ServerId == "ServerX" && s.Type == "Complete" && s.Date >= fromDP.SelectedDate.Value && s.Date <= toDP.SelectedDate.Value)
to filter to a limited date range.
EDIT
As #vvs0205 suggested. Use EntityFunctions class to manipulate the date column as you please: http://msdn.microsoft.com/en-us/library/system.data.objects.entityfunctions.aspx
Something like this
var fromDate = fromDP.SelectedDate.Value;
var toDate= toDP.SelectedDate.Value;
var q = from server in this.db.Servers
where (server.Date >= fromDate && server.Date<=toDate && server.ServerID="ServerX" && server.Type=="Complete")
group server by server.Date
into g
orderby g.Key
select new
{
Date = g.Key,
Count = g.Count()
};
var results = q.ToList();

Categories