2011-08-09 14 views
1

私はLinqのGroupByを使ってストーミングしています。私は1つの表現でそれを行うことはできませんが、問題を解決するための手がかりを持っていないと思います。GroupByとLinq with Objects

public class Shipment { 
    public string PortOfOrigin{get;set;} 
    public string PortOfDestination{get;set;} 
    public ICollection<Invoice> Invoices{get;set;} 
} 

public class Invoice{ 
    public string InvoicePeriod {get;set;} 
    public decimal Amount {get;set;} 
} 

私はすべての請求書のコレクションを持って出荷のコレクションを持っている:

は、私は、次の2つのクラスを持っています。ここに例があります。

List<Shipment> shipments = new List<Shipment> 
{ 
    new Shipment { PortOfOrigin = "USLOS", PortOfDestionation = "UKLON", 
     Invoices = new List<Invoice> 
     { 
      new Invoice{InvoicePeriod = "201106", Amount = 1000}, 
      new Invoice{InvoicePeriod = "201106", Amount = 2000}, 
      new Invoice{InvoicePeriod = "201107", Amount = 1000} 
     } 
    }, 
    new Shipment { PortOfOrigin = "USLOS", PortOfDestionation = "UKLON", 
     Invoices = new List<Invoice> 
     { 
      new Invoice{InvoicePeriod = "201106", Amount = 3000}, 
      new Invoice{InvoicePeriod = "201107", Amount = 2000} 
     } 
    }, 
    new Shipment { PortOfOrigin = "USDAL", PortOfDestionation = "UKLON", 
     Invoices = new List<Invoice> 
     { 
      new Invoice{InvoicePeriod = "201106", Amount = 3000} 
     } 
    } 
}; 

今、私は次でグループ化する:

Shipment.PortOfOrigin、Shipment.PortOfDestionation、Shipment.Invoices.InvoicePeriod。

だから私はこの

PortOfOrigin PortOfDestination InvoicePeriod Amount 
------------------------------------------------------------------------ 
USLOS   UKLON    201106   6000 
USLOS   UKLON    201107   3000 
USDAL   UKLON    201106   3000 

のような結果がInvoices.InvoicePeriodにグループに私がしたい、このようなグループを行うには、これがも可能ですしたいですか?

+0

+1サンプルデータと必要な結果の例については、それはとても明確でよく定義されている質問を得ることはまれです:-) –

+0

ありがとうございます。 –

答えて

1

更新日:私は、出荷数を含めるように答えを更新しました。これには、貨物にIDフィールドが必要です。


以下は、トリックを行います:

enter image description here

UPDATE:

//first flatten the data so it's easier to manipulate 
var query = from s in shipments 
      from i in s.Invoices 
      select new 
      { 
       s.ShipmentUniqueIdentifier, 
       s.PortOfOrigin, 
       s.PortOfDestination, 
       i.InvoicePeriod, 
       i.Amount 
      }; 

//group the data as desired 
var grouping = query.GroupBy(q => new { q.PortOfOrigin, q.PortOfDestination, q.InvoicePeriod }); 

//finally sum the amounts 
var results = from g in grouping 
       select new 
       { 
        g.Key.PortOfOrigin, 
        g.Key.PortOfDestination, 
        g.Key.InvoicePeriod, 
        Amount = g.Select(s => s.Amount).Sum(), 
        NumberOfShipments = g.Select(s => s.ShipmentUniqueIdentifier).Distinct().Count() 
       }; 
ここ

が出力さだ

:約束どおり
、ここでは完全な作業例です
public class Shipment { 
    public Guid ShipmentUniqueIdentifier{get;set;} 
    public string PortOfOrigin{get;set;} 
    public string PortOfDestination{get;set;} 
    public ICollection<Invoice> Invoices{get;set;} 
} 

public class Invoice { 
    public string InvoicePeriod {get;set;} 
    public decimal Amount {get;set;} 
} 

List<Shipment> shipments = new List<Shipment> 
{ 
    new Shipment { PortOfOrigin = "USLOS", PortOfDestination = "UKLON", ShipmentUniqueIdentifier = Guid.NewGuid(), 
     Invoices = new List<Invoice> 
     { 
      new Invoice{InvoicePeriod = "201106", Amount = 1000}, 
      new Invoice{InvoicePeriod = "201106", Amount = 2000}, 
      new Invoice{InvoicePeriod = "201107", Amount = 1000} 
     } 
    }, 
    new Shipment { PortOfOrigin = "USLOS", PortOfDestination = "UKLON", ShipmentUniqueIdentifier = Guid.NewGuid(), 
     Invoices = new List<Invoice> 
     { 
      new Invoice{InvoicePeriod = "201106", Amount = 3000}, 
      new Invoice{InvoicePeriod = "201107", Amount = 2000} 
     } 
    }, 
    new Shipment { PortOfOrigin = "USDAL", PortOfDestination = "UKLON", ShipmentUniqueIdentifier = Guid.NewGuid(), 
     Invoices = new List<Invoice> 
     { 
      new Invoice{InvoicePeriod = "201106", Amount = 3000} 
     } 
    } 
}; 

void Main() 
{ 
    //first flatten the data so it's easier to manipulate 
    var query = from s in shipments 
       from i in s.Invoices 
       select new 
       { 
        s.ShipmentUniqueIdentifier, 
        s.PortOfOrigin, 
        s.PortOfDestination, 
        i.InvoicePeriod, 
        i.Amount 
       }; 

    //group the data as desired 
    var grouping = query.GroupBy(q => new { q.PortOfOrigin, q.PortOfDestination, q.InvoicePeriod }); 

    //finally sum the amounts 
    var results = from g in grouping 
        select new 
        { 
         g.Key.PortOfOrigin, 
         g.Key.PortOfDestination, 
         g.Key.InvoicePeriod, 
         Amount = g.Select(s => s.Amount).Sum(), 
         NumberOfShipments = g.Select(s => s.ShipmentUniqueIdentifier).Distinct().Count() 
        }; 

    //output the results 
    results.Dump(); 
} 
+0

ありがとうございます。はい、私はデータを平らにすることを考えましたが、私はそれを行うために新しいクラスを作成する必要があると思っていましたが、私はあなたの最初のlinqステートメントを使用する場合は、 –

+0

ここにも含まれている出荷数を取得する方法はありますか? g.Count()を追加するだけで、各グループの請求書と同じ番号を得ることになります(それは平坦化されているためです)。だから、どうすればこの例の出荷数を得ることができるのでしょうか?2,2と1。そして、3,2と1ではありません。 –

+0

@Magnus出荷数を与えるために私の答えを更新しました。素晴らしい報酬になる;-)) –