需要C#linq查询数据透视数据

时间:2016-09-27 07:11:15

标签: c# linq

我有一个带有一些字段的Order表。我现在需要其中两个:PostalCodeTimeSlot。结构如下:

DB table structure

我需要的是一个像下面这样的结构(在C#中需要Linq查询)。

Required structure

提前致谢。

2 个答案:

答案 0 :(得分:0)

你可以沿着这些方向做点什么:

//taken from LinqPad. Dump() will not work anywhere else.
void Main()
{
    var source = new List<Order> {
        new Order {ZipCode = "01", TimeSlot ="A" },
        new Order {ZipCode = "02", TimeSlot ="B" },
        new Order {ZipCode = "01", TimeSlot ="B" },
        new Order {ZipCode = "01", TimeSlot ="C" }
    };

    var pivotedOrders = source.GroupBy (s => s.ZipCode)
                              .Select(o => new {
                                ZipCode = o.Key,
                                OrdersCount = o.Count(),
                                A = o.Count(x => x.TimeSlot == "A"),
                                B = o.Count(x => x.TimeSlot == "B"),
                                C = o.Count(x => x.TimeSlot == "C")
                              })
                              .Dump();
}

public class Order
{
    public string ZipCode {get; set; }
    public string TimeSlot {get; set; }
}

结果:

enter image description here

答案 1 :(得分:0)

在LINQ中,您无法动态创建动态对象。您应该尝试ExpandoObject,但老实说,我没有任何经验。

我将采用的解决方案是:我将构建一个像这样的对象,而不是每个时隙都有一个属性的对象:

class PivotData
{
    public string ZipCode { get; set; }
    public int OrdersCount { get; set; }
    public Dictionary<string, int> TimeSlots {get; set;}
}

正如您所看到的,它包含一个字符串,其中键值对为string和int:字符串是时隙的名称,int是计数。

基于此对象,您可以编写LINQ代码,如下所示:

    var source = new List<Order> {
    new Order {ZipCode = "01", TimeSlot ="A" },        
    new Order {ZipCode = "01", TimeSlot ="A" },
    new Order {ZipCode = "02", TimeSlot ="B" },
        new Order {ZipCode = "01", TimeSlot ="B" },
        new Order {ZipCode = "01", TimeSlot ="C" }
    };

    var result = source
        .GroupBy(s => s.ZipCode)
        .Select(g => new PivotData
                {
                    ZipCode = g.Key,
                    OrdersCount = g.Count(),
                    TimeSlots = g.GroupBy(x => x.TimeSlot).ToDictionary(x => x.Key, x => x.Count())
                }).ToList();

    foreach(var item in result) {
        System.Console.WriteLine("ZipCode: " + item.ZipCode + " - " + "Orders count: " + item.OrdersCount);
        Console.WriteLine("Time slots:");
        foreach(var timeSlot in item.TimeSlots) {
            System.Console.WriteLine(timeSlot.Key + " - " + timeSlot.Value);
        }
        Console.WriteLine("---");
    }