Linq to select latest records - c#

I have the data structure
For each item there is a record of it's price on a certain date in each currency. I need to create a query that returns the most current price for each currency.
This query works, but returns multiple Amounts for currency ID 1. It should only return 3 records, 7,8 and 9 as these represent the most up to date prices in all currencies for this item.
var q = (from c in db.tblStoreItemPrices where c.ItemID == ID select new { c.CurrencyID, c.Amount });
Please ignore all ordering and assume that records are randomly ordered.

This should work:
db.tblStoreItemPrices
.Where(c => c.ItemID == ID)
.GroupBy(c => c.CurrencyID)
.Select(g => g.OrderByDescending(c => c.Date).First())
.Select(c => new { c.CurrencyID, c.Amount });
Explanation:
Select rows for the specific ItemID
Group by CurrencyID
From within each currency group select the row that has the most recent date (leaving one row for for each CurrencyID in the result set)
Pull out the information you want from these rows

Related

Linq OrderBy then GroupBy - group by unexpectedly changes order of list

When I run this expression i can see that the list order is correctly in sequence by the highest ActionId's
var list = db.Actions.Where(z => z.RunId
== RunId).OrderByDescending(w =>
w.ActionId).ToList();
I only want to select the highest ActionId's of each ActionName so I now do:
var list = db.Actions.Where(z => z.RunId
== RunId).OrderByDescending(w =>
w.ActionId).GroupBy(c => new
{
c.ActionName,
c.MachineNumber,
})
.Select(y =>
y.FirstOrDefault()).ToList();
When I look at the contents of list, it hasn't selected the ActionName/MachineNumber with the highest ActionId, which I assumed would be the case by ordering then using FirstOrDefault().
Any idea where I'm going wrong? I want to group the records by the ActionName and MachineId, and then pick the record with the highest ActionId for each group
Instead of grouping an ordered collection, group the collection first, and then select the record with the highest ID for each of the groups. GroupBy is not guaranteed to preserve the order in each group in LINQ to SQL - it depends on your database server.
var list = db.Actions.Where(z => z.RunId == RunId).GroupBy(c => new
{
c.ActionName,
c.MachineNumber,
})
.Select(y => y.OrderByDescending(z => z.ActionId).FirstOrDefault()).ToList();

Issues getting a sum of a field grouped by another field in C#

I have basic product object that contains an Id, date and sales count. Each product has one object per day with the total sales for that day. I want to be able to accept a date range and return the top selling products between this date.
I am trying to get the sum of sales within a date range but group them by product ID. So that i can get the total sales for product 123, 234,345 etc within the date range and then get back the top 10 best selling products.
This is what I have written. The response doesnt seem to be correct as each product ID has 10 results. I should only be getting 1 value per product ID, which is the total sales. If it were SQL i want to get the sum of sales grouped by product ID.
var response = ElasticClient.Search<Product>(s => s
.Index(this.Index)
.Query(q => q
.DateRange(dr => dr
.Field(drf => drf.Date)
.GreaterThanOrEquals(startDate)
.LessThan(endDate)
)
)
.Aggregations(ag => ag
.Terms("productResults", pr => pr
.Field(prf => prf.ProductID)
.Size(10)
.Aggregations(prag => prag
.Sum("totalsales", sm => sm
.Field(f => f.TotalSales)
)
)
.Order( o => o.Descending("totalsales"))
)
)
);

How to use Linq to Entity to query results ordered by field in related table in C# windows Forms application?

I have 2 Tables in SQL server database :
Table1:
CustomerID
CustomerName
Table2:
TicketID
TicketDate
CustomerID
related using One(Table1) to Many (Table2)
I want to make linq to entities query using C# to query all customers ORDERED BY TicketDate descending, so that i can list all DISTINCT names of customers in combobox with customers who have most recent tickets viewed at the top
Assuming Table2 doesn't have 10+ times the number of records of Customer you can change things around. OrderBy Tickets and select Customer
//Gets a list of all customers, sorted by ticket date
List<Table1> customers = entities.Table2
.OrderByDescending(t => t.TicketDate)
.Select(t => t.Table1)
.Distinct()
.ToList();
If Table2 has a lot more records (10+ times the number of records or just billions) you should start with Customer and use Max date, so the query on the database does the same and doesn't do an exact reordering for each Customer.
List<Table1> customers = entities.Table1
.OrderByDescending(c => c.Table2.Max(t => t.TicketDate))
.ToList();
EDIT
I think this is the option that you should use, since it doesn't result in a subquery per record to determine MAX, but performs MAX on each group
List<Table1> customers = entities.Table2
.GroupBy(t => t.Table1)
.OrderByDescending(g => g.Max(t => t.TicketDate))
.Select(g => g.Key)
.ToList();
I'm not 100% sure what you want, is this what you are looking for?
using (DatabaseEntities entities = new DatabaseEntities())
{
//Gets a list of all customers, sorted by ticket date
List<Table1> customers = entities.Table1
.OrderByDescending(x => x.Table2.Select(y => y.TicketDate).OrderByDescending(y => y.TicketDate)
.FirstOrDefault().TicketDate)
.ToList();
}

Order a list of string by quantity

I have a list of string that i want to order by quantity. The List contain a list of Order-CreationDate with datetime values. I'm converting this values to strings as as i will need that for later.
My current output is a list of CreationDate that looks like this.
2014-04-05
2014-04-05
2014-04-05
2014-04-05
2014-04-06
2014-04-06
2014-04-06
...
I get a list of dates as expected but i want to group number of dates by the date. This mean i need another variable with number of total orders. Ive tried creating a new variable, using a for loop and linq queries but not getting the results I want.
How can I get number of orders by CreationDate? I need to count total number of orders by CreationDate but I can't find a way to do this.
The expected output would be:
2014-04-05 4 - representing 4 orders that date
2014-04-06 3 - representing 3 orders that date.
This what my code looks like:
List<string> TotalOrdersPaid = new List<string>();
foreach (var order in orders)
{
if (order.PaymentStatus == PaymentStatus.Paid)
{
string Created = order.CreatedOnUtc.Date.ToString("yyyy-MM-dd");
order.CreatedOnUtc = DateTime.ParseExact(Created, "yyyy-MM-dd", CultureInfo.InvariantCulture);
TotalOrdersPaid.Add(Created);
}
}
Eg TotalOrdersPaid should contain a list with number of orders by CreationDate.
What is a good way to achieve this?
Thanks
basically, you just need a group by and and ordering.
var result = orders//add any where clause needed
.GroupBy(m => m)
.Select(m => new {
cnt = m.Count(),
date = m.Key
})
.OrderByDescending(m => m.cnt);
Of course, you can add any DateTime.Parse / ParseExact in the Select, and / or project to a corresponding class.
To group the orders by date, take following LinQ lambda expression:
var grouped = orders.Where(o => o.PaymentStatus == PaymentStatus.Paid)
.GroupBy(g => g.CreatedOnUtc);
Now, all paid orders are grouped by date. To count the orders per date, select the key which is the date, and the Count() will count all orders for that date.
var counted = grouped.Select(s => new { Date = s.Key, Count = s.Count() });
Edit:
In one statement:
var result = orders.Where(o => o.PaymentStatus == PaymentStatus.Paid)
.GroupBy(g => g.CreatedOnUtc)
.Select(s => new { Date = s.Key, Count = s.Count() });
Based on your list of dates, the output will look like:
Date Count
5/04/2014 4
6/04/2014 3
Update:
If you want to put more properties in the anonymous type that will be returned from the Select() method, sumply just add them. If, for example, you want the date, the count and the list of orders for that date, use following line of code:
var result = orders.Where(o => o.PaymentStatus == PaymentStatus.Paid)
.GroupBy(g => g.CreatedOnUtc)
.Select(s => new
{
Date = s.Key,
Count = s.Count(),
Items = s.ToList()
});
Now you can do following:
foreach(var orderGroup in result)
{
Console.WriteLine(String.Format("Number of orders for {0}: {1}", orderGroup.Date, orderGroup.Count));
foreach(var order in orderGroup.Items)
{
Console.WriteLine(order.Name);
}
}
This will loop over all grouped items and display a sentence like:
Number of orders for 5/04/2014: 4
And then it will display the name of each order for that date (if your order has a property Name). Hope this clears everything out.

How to order items with LINQ?

The idea is. I have items which initially I would like to order by DateCreated. Last created shows first in a grid.
But I have some items which have LastDateTime. If LastDateTime < DateTime.Now I need to show them after all most current items. So they have to be at the end.
Example of needed output results:
# Item DateCreated LastDate
--------------------------------------------------------------------------
1. Item 1 07-11-2011 07-29-2011
2. Item 2 07-10-2011 07-29-2011
3. Item 3 07-09-2011 07-29-2011
4. Item 4 07-08-2011 07-29-2011
5. Item 5 07-16-2011 07-18-2011
6. Item 6 07-13-2011 07-15-2011
7. Item 7 07-11-2011 07-12-2011
Tables:
-------------------------------------------------
ID (PK) Item (string) DateCreated (DateTime)
Table 2
-------------------------------------------------
DayID (PK) ID (FK) DateTimeUtc (DateTime)
Here is example of my linq query. It shows all items with last day < date time now at the end. but it doesn't show properly order by created date.
return (from i in _entity.Items
join d in _entity.Days
on i.ID equals d.ID into leftJoinTable
where i.ID == 123
select new
{
i.ID,
i.Item,
LastDate = leftJoinTable.OrderByDescending(a => a.DayID)
.Select(a => a.DateTimeUtc)
.FirstOrDefault()
}).Distinct()
.OrderByDescending(x => x.ID)
.ThenBy(x=>x.LastDate)
.ToList();
Try ordering by DayID in your last OrderByDescending.
return (from i in _entity.Items
join d in _entity.Days
on i.ID equals d.ID into leftJoinTable
where i.ID == 123
select new
{
i.ID,
i.Item,
LastDate = leftJoinTable.OrderByDescending(a => a.DayID)
.Select(a => a.DateTimeUtc)
.FirstOrDefault()
}).Distinct()
.OrderByDescending(x => x.ID) // You're ordering by ID first
.ThenBy(x=>x.LastDate)
.ToList();
EDIT: Ah sorry didn't see that. My best guess is that since your ordering by ID first which would almost cancel out the LastDate ordering. You said you need them ordered by LastDate first correct? Does it matter on the order of the ID's? If not just .OrderByDescending(x => x.LastDate)

Categories

Resources