创建一个允许用户接受订单的C#WPF应用程序(想想餐厅/酒吧)。
为简单起见,我将订单限制为单个商品的简单购买(您可以购买多件商品,例如购买4瓶啤酒)。每次购买都记录为购买对象:
class Purchase
{
public int id {get;set;}
public DateTime time {get;set;}
public double price {get;set;}
public int quantity {get;set;}
}
并且每次购买都会添加到DataTable中。
我希望在给定时间内获得最多3个和3个最少购买的商品,而我却无法为此编写合适的查询。
到目前为止,我所拥有的是这个,但它不起作用:
public List<int> GetMostBought()
{
DateTime lastMinute = DateTime.UtcNow.Add(new TimeSpan(0, -1, 0)); //one minute ago
int howMany = 3; // how many items to get.
var query =
(from p in purchases.AsEnumerable()
where p.Field<DateTime>("time")>= lastMinute //purchases made less than a minute ago
select new { Product = p, Quantity = p.Field<int>("quantity") } into productQty
group productQty by productQty.Product into pg
let totalQuantity = pg.Sum(prod => prod.Quantity)
orderby totalQuantity descending
select pg.Key).Take(howMany);
List<int> mostBoughtIDs = new List<int>();
foreach (DataRow dr in query)
{
mostBoughtIDs.Add(Int32.Parse(dr[0].ToString()));
}
return mostBoughtIDs;
有什么想法吗?
答案 0 :(得分:2)
var mostBoughtIDs = purchases.AsEnumerable()
.Where(r=>r.Field<DateTime>("time")>= lastMinute)
.GroupBy(r=>r.Field<int>("id"))
.OrderByDescending(g=>g.Sum(r=>r.Field<int>("quantity"))
.Select(g=>g.First().Field<int>("id"))
.Take(howMany);
答案 1 :(得分:1)
var items =
purchases.AsEnumerable()
.Where(e => e.Field<DateTime>("time") >= lastMinute)
.GroupBy( g => g.Field<int>("id") )
.OrderByDecending( i => i.Sum( e => e.Field<int>("quantity") ) )
.Select( g => g.First().Field<int>("id"))
.Take(3)
答案 2 :(得分:0)
您可以使用找到here:
的漂亮小方法从列表创建DataTablepublic DataTable ConvertToDataTable<T>(IList<T> data)
{
PropertyDescriptorCollection properties =
TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}
public List<int> GetMostAndLeastBought(int howMany){
List<Purchase> purchasesList = new List<Purchase>{
new Purchase{ id = 1, time = DateTime.UtcNow.Add(new TimeSpan(0, 0, -1)), quantity = 1},
new Purchase{id = 1, time = DateTime.UtcNow.Add(new TimeSpan(0, 0, -1)), quantity = 1},
new Purchase{id = 2, time = DateTime.UtcNow.Add(new TimeSpan(0, 0, -1)), quantity = 1},
new Purchase{id = 2, time = DateTime.UtcNow.Add(new TimeSpan(0, 0, -1)), quantity = 1},
new Purchase{id = 3, time = DateTime.UtcNow.Add(new TimeSpan(0, 0, -1)), quantity = 1},
new Purchase{id = 3, time = DateTime.UtcNow.Add(new TimeSpan(0, 0, -1)), quantity = 1},
new Purchase{id = 4, time = DateTime.UtcNow.Add(new TimeSpan(0, 0, -1)), quantity = 1},
new Purchase{id = 4, time = DateTime.UtcNow.Add(new TimeSpan(0, 0, -1)), quantity = 1},
new Purchase{id = 5, time = DateTime.UtcNow.Add(new TimeSpan(0, 0, -1)), quantity = 1},
new Purchase{id = 6, time = DateTime.UtcNow.Add(new TimeSpan(0, 0, -1)), quantity = 1},
new Purchase{id = 7, time = DateTime.UtcNow.Add(new TimeSpan(0, 0, -1)), quantity = 1}
};
DataTable purchases = ConvertToDataTable(purchasesList);
我认为查询语法在这里也可以很好地用于主查询:
DateTime lastMinute = DateTime.UtcNow.Add(new TimeSpan(0, -1, 0)); //one minute ago
var query = from p in purchases.AsEnumerable()
where p.Field<DateTime>("time") >= lastMinute
group p by p.Field<int>("id") into g
select new {Id = g.Key, TotalQuantity = g.Sum(x => x.Field<int>("quantity"))} into s
orderby s.TotalQuantity descending, s.Id
select s.Id;
如果你想同时获得最多和最少的话,你可以得到最多和最少。你想在做之前转换List,因为那样你就可以有效地获得最后的元素,如:
var list = query.ToList();
var most = list.GetRange(0, howMany);
var least = list.GetRange(list.Count - howMany, howMany);