0

私はまだLINQを学んでおり、Bookingオブジェクトを4つのプロパティでグループ化し、入力時間範囲に応じて毎週の間隔でグループ化する必要があるタスクがあります。

public class Booking
{
    public string Group { get; set; }
    public BookingType Type { get; set; }
    public BookingStatus Status { get; set; }
    public decimal Price { get; set; }
    public bool Notification { get; set; }
    public DateTime Date { get; set; }
}

次の予約があるとします。

        IList<Booking> Bookings = new List<Booking>
        {
            new Booking{Group = "Group1", Type = BookingType.Online, Status = BookingStatus.New, Price = 150, Date = new DateTime(2012,06,01)},
            new Booking{Group = "Group1", Type = BookingType.Online, Status = BookingStatus.New, Price = 100, Date = new DateTime(2012,06,02)},
            new Booking{Group = "Group1", Type = BookingType.Online, Status = BookingStatus.New, Price = 200, Date = new DateTime(2012,06,03)},

            new Booking{Group = "Group2", Type = BookingType.Phone, Status = BookingStatus.Accepted, Price = 80, Date = new DateTime(2012,06,10)},
            new Booking{Group = "Group2", Type = BookingType.Phone, Status = BookingStatus.Accepted, Price = 110, Date = new DateTime(2012,06,12)},

            new Booking{Group = "Group3", Type = BookingType.Store, Status = BookingStatus.Accepted, Price = 225, Date = new DateTime(2012,06,20)},

            new Booking{Group = "Group3", Type = BookingType.Store, Status = BookingStatus.Invoiced, Price = 300, Date = new DateTime(2012,06,21)},
            new Booking{Group = "Group3", Type = BookingType.Store, Status = BookingStatus.Invoiced, Price = 140, Date = new DateTime(2012,06,22)},
        };

これにより、最終的な印刷物に次の行が表示されます。

                                        Week 22     Week 23     Week 24     Week 25     Week 26
                                        May28-Jun3  Jun4-10     Jun11-17    Jun18-24    Jun25-Jul1
            Group   Type    Status      Cnt. Price  Cnt. Price  Cnt. Price  Cnt. Price  Cnt. Price
            ----------------------------------------------------------------------------------------------
            Group1  Online  New         3   450     0   0       0   0       0   0       0   0
            Group2  Phone   Accepted    0   0       1   80      1   110     0   0       0   0
            Group3  Store   Accepted    0   0       0   0       0   0       1   225     0   0       
            Group3  Store   Invoiced    0   0       0   0       0   0       2   440     0   0           

任意の数の週を含める可能性のある行を表すために、2 つの追加クラスを作成しました。

 public class GroupedLine
{
    public string Group { get; set; }
    public BookingType Type { get; set; }
    public BookingStatus Status { get; set; }
    public List<WeeklyStat> WeeklyStats { get; set; } 
}

public class WeeklyStat
{
    public DateTime WeekStart { get; set; }
    public decimal Sum { get; set; }
    public int Count { get; set; }
}

次の期間がある場合:

        var DateFrom = new DateTime(2012, 05, 28);
        var DateTo = new DateTime(2012, 7, 01);

まず、統計に必要な週を特定する必要があります。この場合は 22 ~ 26 週です。

そのために、次のコードがあります。

        var DateFrom = new DateTime(2012, 05, 28);
        var DateTo = new DateTime(2012, 7, 01);

        var firstWeek = GetFirstDateOfWeek(DateFrom, DayOfWeek.Monday);
        IList<DateTime> weeks = new List<DateTime> { firstWeek };

        while(weeks.OrderByDescending(w => w).FirstOrDefault().AddDays(7) <= DateTo)
        {
            weeks.Add(weeks.OrderByDescending(w => w).FirstOrDefault().AddDays(7));
        }

そして今、4 つのプロパティと集計 (予約の数と価格の合計) の両方でグループ化を行うには、LINQ マジックが必要です。

これまでに入手した LINQ のコード サンプルは、現在アクセスできないため、明日添付できます。長い投稿で申し訳ありませんが、私の言いたいことが明確であることを願っています。

編集: 2012-11-07 グループ化された週に実際にデータがある週のみが含まれるように、質問を少し変更する必要があります。更新された出力例:

                                        May28-Jun3  Jun4-10     Jun18-24    
            Group   Type    Status      Cnt. Price  Cnt. Price  Cnt. Price  
            ---------------------------------------------------------------
            Group1  Online  New         3   450     0   0       0   0       
            Group2  Phone   Accepted    0   0       1   80      0   0       
            Group3  Store   Accepted    0   0       0   0       1   225             
            Group3  Store   Invoiced    0   0       0   0       2   440         

この場合、期間 6 月 11 ~ 17 日および 6 月 25 日 ~ 7 月 1 には予約がなかったため、結果から除外されます。

4

3 に答える 3

1

このクエリはすべてのデータを取得します

var query = from b in Bookings
            where b.Date >= dateFrom && b.Date <= dateTo
            group b by new { b.Group, b.Type, b.Status } into g
            select new GroupedLine()
            {
                Group = g.Key.Group,
                Type = g.Key.Type,
                Status = g.Key.Status,
                WeeklyStats = (from b in g
                                let startOfWeek = GetFirstDateOfWeek(b.Date)
                                group b by startOfWeek into weekGroup
                                orderby weekGroup.Key
                                select new WeeklyStat() 
                                {
                                    WeekStart = weekGroup.Key,
                                    Count = weekGroup.Count(),
                                    Sum = weekGroup.Sum(x => x.Price)

                                }).ToList()
            };

UI出力はあなたに任せます:)

これにより、すべての週の WeekStats も返されます (一部の週に予約グループがない場合、値は 0 になります)。

// sequence contains start dates of all weeks
var weeks = Bookings.Select(b => GetFirstDateOfWeek(b.Date))
                    .Distinct().OrderBy(date => date);

var query = from b in Bookings
            group b by new { b.Group, b.Type, b.Status } into bookingGroup
            select new GroupedLine()
            {
               Group = bookingGroup.Key.Group,
               Type = bookingGroup.Key.Type,
               Status = bookingGroup.Key.Status,
               WeeklyStats = (from w in weeks
                              join bg in bookingGroup 
                              on w equals GetFirstDateOfWeek(bg.Date) into weekGroup
                              orderby w
                              select new WeeklyStat() 
                              {
                                  WeekStart = w,
                                  Count = weekGroup.Count(),
                                  Sum = weekGroup.Sum(b => b.Price)    
                              }).ToList()
            };

日付フィルター (from、to) が必要な場合は、weeksクエリとbookingsクエリの両方に適用する必要があることに注意してください。

于 2012-10-17T19:23:09.727 に答える
0

このバリアントは、データのない週に「空の」スポットを生成します。

// I group by week number, it seemed clearer to me , but you can change it
var firstWeek = cal.GetWeekOfYear(DateFrom, dfi.CalendarWeekRule, dfi.FirstDayOfWeek);
var lastWeek  = cal.GetWeekOfYear(DateTo, dfi.CalendarWeekRule, dfi.FirstDayOfWeek);

var q = from b in Bookings
        group b by new { b.Group, b.Type, b.Status }
        into g
        select new 
        {
            Group = g.Key,
            Weeks = 
                from x in g
                select new 
                { 
                    Week = cal.GetWeekOfYear(x.Date,
                                             dfi.CalendarWeekRule, 
                                             dfi.FirstDayOfWeek), 
                    Item = x 
                }   
        } into gw
        from w in Enumerable.Range(firstWeek, lastWeek-firstWeek+1) 
        select new 
        { 
            gw.Group,
            Week = w,
            Item = from we in gw.Weeks
                   where we.Week == w
                   group we by we.Item.Group into p 
                   select new 
                   {
                       p.Key,
                       Sum = p.Sum (x => x.Item.Price),
                       Count = p.Count()
                   }
        };
于 2012-10-17T20:08:49.560 に答える
0
var query = Bookings.GroupBy(book => new GroupedLine()
{
    Group = book.Group,
    Type = book.Type,
    Status = book.Status
})
.Select(group => new
{
    Line = group.Key,
    Dates = group.GroupBy(book => GetWeekOfYear(book.Date))
        .Select(innerGroup => new
        {
            Week = innerGroup.Key,
            Count = innerGroup.Count(),
            TotalPrice = innerGroup.Sum(book => book.Price)
        })
});

public static int GetWeekOfYear(DateTime date)
{
    return date.DayOfYear % 7;
}
于 2012-10-17T19:02:31.160 に答える