0

一部の月にデータが含まれていない場合でも、すべてのデータを月ごとにグループ化できるようにしたいと思います。現時点ではグループ化できますが、返されるデータには数か月分のデータしか含まれていません。

これが私のコードがどのように見えるかです:

var twelveMonthAgo = date.AddMonths(-12).Date;
var twelveMonthAgoFirstOfMonth = new DateTime(twelveMonthAgo.Year, twelveMonthAgo.Month, 1, 0, 0, 0, 0);

var data = (from i in Database.Users
            where i.RegisterDate >= twelveMonthAgoFirstOfMonth
            group i by new {y=i.RegisterDate.Year,m = i.RegisterDate.Month} into g
            select new UserStatistic{ Date = EntityFunctions.CreateDateTime(g.Key.y, g.Key.m, 1, 0, 0, 0)
                                       , UserCount = g.Count(o => o.Id)
                                     });

//The code below is what I would like to remove                                         
var toReturn = new List<UserStatistic>();
var allData = data.ToList();
DateTime datei = twelveMonthAgoFirstOfMonth;
while (datei.Year<= date.Year && datei.Month<=date.Month){
    var info = allData.SingleOrDefault(x => x.Date.HasValue && x.Date.Value.Year == datei.Year && x.Date.Value.Month == datei.Month);
    toReturn.Add(info ?? new UserStatistic { Date = datei, UserCount = 0, PaymentPaid = 0 });
    datei = datei.AddMonths(1);
}
return toReturn.AsQueryable();   

ご覧のとおり、コメントの下のコードは過去12か月のコレクションを作成し、データベースからデータが削除されているかどうかを確認し、存在する場合はコレクションを埋めます。存在しない場合は0を入力します。

コメントの下のコードを実行せずに、どうすればそれをすべて実行できますか?

4

2 に答える 2

1

サブクエリへのグループ結合を使用して目的の結果を取得するコードを次に示します。

DateTime date = DateTime.Today;
DateTime firstOfMonth = new DateTime(date.Year, date.Month, 1);
DateTime twelveMonthAgoFirstOfMonth = firstOfMonth.AddMonths(-12);

// Generate a collection of the months and years for the last 12 months
var monthYears = Enumerable.Range(-12, 12).Select(monthOffset => { DateTime monthDate = firstOfMonth.AddMonths(monthOffset); return new { y = monthDate.Year, m = monthDate.Month }; });

// Go through the list of months and years and join them to the users retrieved from the database in the subquery.
var data = from monthYear in monthYears
           join i in (from i in Database.Users
                      where i.RegisterDate >= twelveMonthAgoFirstOfMonth && i.RegisterDate < firstOfMonth
                      select i) on monthYear equals new { y = i.RegisterDate.Year, m = i.RegisterDate.Month } into gj
           select new UserStatistic() { Date = new DateTime(monthYear.y, monthYear.m, 1), UserCount = gj.Count() });

これは、左外部結合を持つサブクエリのグループとして表すこともできます。

    DateTime date = DateTime.Today;
    DateTime firstOfMonth = new DateTime(date.Year, date.Month, 1);
    DateTime twelveMonthAgoFirstOfMonth = firstOfMonth.AddMonths(-12);
    var monthYears = Enumerable.Range(-12, 12).Select(monthOffset => { DateTime monthDate = firstOfMonth.AddMonths(monthOffset); return new { y = monthDate.Year, m = monthDate.Month }; });

    var data = (from monthYear in monthYears
                join i in (from i in Database.Users
                           where i.RegisterDate >= twelveMonthAgoFirstOfMonth && i.RegisterDate < firstOfMonth
                           group i by new {y = i.RegisterDate.Year, m = i.RegisterDate.Month} into g
                           select new { Key = g.Key, UserCount = g.Count() }) on monthYear equals i.Key into j
                 from k in j.DefaultIfEmpty()
                 select new UserStatistic() { Date = new DateTime(monthYear.y, monthYear.m, 1), UserCount = k != null ? k.UserCount : 0 });

私はあなたのEFモデルを持っていないので、それを試して、に置き換える必要があるかどうかを確認する必要がありnew DateTimeますEntityFunctions.CreateDateTime

于 2012-07-25T17:30:17.700 に答える
1

私はこれをコンパイルしてデバッグしていませんが、問題を解決する方法がわかるはずです。私はEnumerable.Rangeあなたが必要とする月のプレースホルダーのセットを生成するために使用します。次に、左からへplaceHoldersの結合dataとマージ、または単に省略を連結するかを選択する必要がありました。

また、理解しやすいように、質問のコードを少し修正しました。

IQueryable<UserStatistic> GetPastMonths(int months)
{    
    var limitDay = date.AddMonths(-months).Date;
    var limit = new DateTime(limitDay.Year, limitDay.Month, 1, 0, 0, 0, 0);

    var placeHolders = Enumerable.Range(0, months + 1)
        .Select(m =>
            new UserStatistic
                {
                    Date = limit.AddMonths(-m),
                    UserCount = 0
                });

    var data = Database.Users
        .Where(i => i.RegisterDate >= limit)
        .GroupBy(i => new {y=i.RegisterDate.Year, m = i.RegisterDate.Month})
        .Select(g => 
            new UserStatistic
                { 
                    Date = EntityFunctions.CreateDateTime(
                            g.Key.y,
                            g.Key.m, 
                            1, 
                            0, 
                            0, 
                            0),
                    UserCount = g.Count(o => o.Id)
                });

    return data.Concat(placeHolders
        .Where(p => !data.Any(d => d.Date == p.Date)))
        .AsQueryable();
}

省略アプローチを連結することは、データを非論理的な順序で返すことをほぼ保証しますが、order by句を使用しない限り、とにかく保証はありません。

于 2012-07-25T16:49:08.230 に答える