Adding more parameters to a Linq query - c#

I'm using this query to count number of orders by date. I'm trying to add one more parameter that counts total products for each order, however I can't get it to work atm.
This is the essential part of a method that is suposed to return a list of 3 parameters (Date, TotalOrders and TotalProducts). Im using a Linq query to get a list with total order for each date, im wondering how to add my third parameter to the list "TotalProducts" and if i can do by adding one more search parameter in the Query. The foreach part below do not work propertly, it will return a list of TotalProducts but CreationDate will be the same for ech item in the list. I also have a feeling putting a foreach inside a foreach dosn't seem optimal for this:
var orders = _orderService.SearchOrderStatistics(startDateValue, endDateValue, orderStatus,
paymentStatus, shippingStatus, model.CustomerEmail, model.OrderGuid);
var result = orders.Where(o => o.PaymentStatus == PaymentStatus.Paid)
.GroupBy(g => g.CreatedOnUtc.Date.ToString("yyyyMMdd"))
.Select(s => new { Date = s.Key, Count = s.Count() });
List<GCOrdersModel> TotalOrdersPaid = new List<GCOrdersModel>();
foreach (var g in result)
{
foreach (var opv in orders)
{
GCOrdersModel _Om = new GCOrdersModel(g.Date, g.Count.ToString(), opv.OrderProductVariants.Count.ToString());
TotalOrdersPaid.Add(_Om);
}
}
return TotalOrdersPaid;
To access total products for every orders I must use OrderProductVariants.Count.ToString()
Can I add this parameter to the query?
Thx

You could try this:
return orders.Where(o => o.PaymentStatus == PaymentStatus.Paid)
.GroupBy(g => g.CreatedOnUtc.Date.ToString("yyyyMMdd"))
.Select(s => new GCOrdersModel()
{
Date = s.Key,
Count = s.Count(),
OpvCount = opv.OrderProductVariants.Count.ToString()
})
.ToList();
or
return orders.Where(o => o.PaymentStatus == PaymentStatus.Paid)
.GroupBy(g => g.CreatedOnUtc.Date.ToString("yyyyMMdd"))
.Select(s => new GCOrdersModel(s.Key, s.Count, opv.OrderProductVariants.Count.ToString()))
.ToList();
That way, you don't have to iterate over your result again. And it automatically creates your list of GCOrdersModel.
Edit
Does this work?
return orders.Where(o => o.PaymentStatus == PaymentStatus.Paid)
.GroupBy(g => g.CreatedOnUtc.Date.ToString("yyyyMMdd"))
.Select(s => new GCOrdersModel()
{
Date = s.Key,
Count = s.Count(),
OpvCount = s.OrderProductVariants.Count.ToString()
})
.ToList();
or
return orders.Where(o => o.PaymentStatus == PaymentStatus.Paid)
.GroupBy(g => g.CreatedOnUtc.Date.ToString("yyyyMMdd"))
.Select(s => new GCOrdersModel(s.Key, s.Count(), s.OrderProductVariants.Count.ToString()))
.ToList();

How about:
var opvCount =
opv
.OrderProductVariants
.Count
.ToString();
return
orders
.Where(o => o.PaymentStatus == PaymentStatus.Paid)
.GroupBy(g => g.CreatedOnUtc.Date.ToString("yyyyMMdd"))
.Select(s => new
{
Date = s.Key,
Count = s.Count()
})
.Select(x =>
new GCOrdersModelg(x.Date, g.Count.ToString(), opvCount));

Related

Mysql to Linq query

MySQL Query
select MAX(os.aggregate_date) as lastMonthDay,os.totalYTD
from (SELECT aggregate_date,Sum(YTD) AS totalYTD
FROM tbl_aggregated_tables
WHERE subscription_type = 'Subcription Income'
GROUP BY aggregate_date) as os
GROUP by MONTH(os.aggregate_date),YEAR(os.aggregate_date)
ORDER BY lastMonthDay;
converted to this LINQ query
var income = context.tbl_aggregated_tables
.Where(s => s.subscription_type == "Subcription Income")
.GroupBy(s => s.aggregate_date)
.Select(result => new
{
date = result.Key,
ytdsum = result.Select(x => x.YTD).Sum()
})
.GroupBy(s => new { month = s.date.Month, year = s.date.Year })
.Select(
// select max data and take its ytdsum value
).ToList();
The purpose of second grouping is to find the max day of each month with a year.
Now, How to select the max date of each month and its ytdsum after the second Grouping?
update
income = context.tbl_aggregated_tables
.Where(s => s.subscription_type == "Subcription Income")
.GroupBy(s => s.aggregate_date)
.Select(result => new
{
date = result.Key,
ytdsum = result.Select(x => x.YTD).Sum()
})
.GroupBy(s => new { s.date.Month, s.date.Year })
.Select(
x => x.Max(s => s.date)
).ToList()
this way it's only return the dates and i could not return the full object of the list including ytdSum.
This should work:
var income = context.tbl_aggregated_tables
.Where(s => s.subscription_type == "Subcription Income")
.GroupBy(s => s.aggregate_date)
.Select(result => new
{
date = result.Key,
ytdsum = result.Select(x => x.YTD).Sum()
})
.GroupBy(s => new { month = s.date.Month, year = s.date.Year })
.Select(
x => x.OrderByDescending(k => k.date).First()
).ToList();
income now is a list of objects, each of them have date and ytdsum
this worked good but it takes much more time than the original mysql query.
var income = context.tbl_aggregated_tables
.Where(s => s.subscription_type == "Subcription Income"
)
.GroupBy(s => s.aggregate_date)
.Select(result => new
{
date = result.Key,
ytdsum = result.Select(x => x.YTD).Sum()
})
.GroupBy(s => new { s.date.Month, s.date.Year })
.Select(
x => x.OrderByDescending(s => s.date)
)
.ToList()
.Select(el => el.FirstOrDefault())
.OrderBy(s=>s.date);

Return additional column in Linq Query?

I have this Linq query:
var area = db.MyDbSet
.Where(s => s.langid == langid)
.GroupBy(s => s.Title)
.Select(g => new { Title = g.Key })
.Select(s => s.Title);
I want to return another column from the same table, its called: CodeId.
I am noob Linq programmer and quite lost in all those mish-mash things in C# so I can't really understand what should I do.
Can somebody help me how to return the another column from the same table with the same query call?
This may help you :
var area = db.MyDbSet
.Where(s => s.langid == langid)
.GroupBy(s => s.Title)
.Select(g => new { Title = g.Key, CodeId = g.FirstOrDefault().CodeId });
var area = db.MyDbSet
.Where(s => s.langid == langid)
.GroupBy(s => s.Title)
.Select(g => new {
Title = g.Key,
CodeId = g.Id,
OtherField = "Field"
})

implement dense rank with linq

Using the following linq code, how can I add dense_rank to my results? If that's too slow or complicated, how about just the rank window function?
var x = tableQueryable
.Where(where condition)
.GroupBy(cust=> new { fieldOne = cust.fieldOne ?? string.Empty, fieldTwo = cust.fieldTwo ?? string.Empty})
.Where(g=>g.Count()>1)
.ToList()
.SelectMany(g => g.Select(cust => new {
cust.fieldOne
, cust.fieldTwo
, cust.fieldThree
}));
This does a dense_rank(). Change the GroupBy and the Order according to your need :)
Basically, dense_rank is numbering the ordered groups of a query so:
var DenseRanked = data.Where(item => item.Field2 == 1)
//Grouping the data by the wanted key
.GroupBy(item => new { item.Field1, item.Field3, item.Field4 })
.Where(#group => #group.Any())
// Now that I have the groups I decide how to arrange the order of the groups
.OrderBy(#group => #group.Key.Field1 ?? string.Empty)
.ThenBy(#group => #group.Key.Field3 ?? string.Empty)
.ThenBy(#group => #group.Key.Field4 ?? string.Empty)
// Because linq to entities does not support the following select overloads I'll cast it to an IEnumerable - notice that any data that i don't want was already filtered out before
.AsEnumerable()
// Using this overload of the select I have an index input parameter. Because my scope of work is the groups then it is the ranking of the group. The index starts from 0 so I do the ++ first.
.Select((#group , i) => new
{
Items = #group,
Rank = ++i
})
// I'm seeking the individual items and not the groups so I use select many to retrieve them. This overload gives me both the item and the groups - so I can get the Rank field created above
.SelectMany(v => v.Items, (s, i) => new
{
Item = i,
DenseRank = s.Rank
}).ToList();
Another way is as specified by Manoj's answer in this question - But I prefer it less because of the selecting twice from the table.
So if I understand this correctly, the dense rank is the index of the group it would be when the groups are ordered.
var query = db.SomeTable
.GroupBy(x => new { x.Your, x.Key })
.OrderBy(g => g.Key.Your).ThenBy(g => g.Key.Key)
.AsEnumerable()
.Select((g, i) => new { g, i })
.SelectMany(x =>
x.g.Select(y => new
{
y.Your,
y.Columns,
y.And,
y.Key,
DenseRank = x.i,
}
);
var denseRanks = myDb.tblTestReaderCourseGrades
.GroupBy(x => new { x.Grade })
.OrderByDescending(g => g.Key.Grade)
.AsEnumerable()
.Select((g, i) => new { g, i })
.SelectMany(x =>
x.g.Select(y => new
{
y.Serial,
Rank = x.i + 1,
}
));

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();

How to find `Distinct` records in LINQ?

I want to find distinct records in entity framework. My code is as below
var distinctYear = _objCalRepos
.GetDetails()
.Select(o => new CalendarList { Mdate = o.Mdate.Year.ToString() })
.Distinct()
.ToList();
ddlYear.DataSource = distinctYear;
ddlYear.DataTextField = "Mdate";
ddlYear.DataValueField = "Mdate";
ddlYear.DataBind();
Here Distinct not works. It will return all entries(duplicated).
Distinct is not working, probably because CalendarList is not comparable.
Try this:
var distinctYear = _objCalRepos
.GetDetails()
.Select(o => o.Mdate.Year.ToString())
.Distinct()
.AsEnumerable()
.Select(o => new CalendarList { Mdate = o }))
.ToList();
You can use GroupBy
var distinctYear = _objCalRepos
.GetDetails()
.Select(o => new CalendarList { Mdate = o.Mdate.Year.ToString() })
.GroupBy(cl => cl.Mdate )
.Select(g => g.First())
.ToList();

Categories