0

我正在创建一个 C# WPF 应用程序,让用户接受订单(想想餐厅/酒吧)。

为简单起见,我将订单限制为对单个商品的简单购买(您可以购买多个商品,例如购买 4 杯啤酒)。每个购买都记录为一个 Purchase 对象:

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;

有任何想法吗?

4

3 回答 3

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);
于 2013-08-28T19:13:49.397 回答
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)
于 2013-08-28T19:25:42.020 回答
0

您可以使用此处找到的一个不错的小方法从列表创建 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);
于 2013-08-28T20:05:40.870 回答