获取C#datatable中的大多数/最少销售的项目

时间:2013-08-28 19:06:46

标签: c# linq datatable linq-to-objects nested-queries

创建一个允许用户接受订单的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;

有什么想法吗?

3 个答案:

答案 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

的漂亮小方法从列表创建DataTable
public 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);