簡體   English   中英

LINQ按日期分組-包括空天,不使用連接

[英]LINQ group by date - include empty days WITHOUT using join

使用C#,NHibernate,NHibernate到LINQ。 使用NHibernate到LINQ,我沒有JOIN功能。 我也不能使用QueryOver。

我有一個LINQ查詢,它計算潛在客戶和銷售量。 該表僅在完成新的潛在客戶或銷售時創建,因此某些天沒有插入任何行。 執行以下查詢

var query3 = query2.AsEnumerable()
           .Where(x => x.Created <= toDate.Value && x.Created >= fromDate.Value)
           .GroupBy(x => x.Created.Date)
           .Select(g => new ReferrerChart {
               Date = g.Key.Date,
               LeadsCount = g.Count(x => !x.IsSale),
               SalesCount = g.Count(x => x.IsSale)
           });

但是某些日期不在其中(日期有0個潛在顧客和銷售)。

如何包含這些日期,並允許它們不使用join設置LeadsCount = 0和SalesCount = 0而沒有?

編輯:

起作用的最終結果:

var selectedFromDate = fromDate.Value;
var selectedToDate = toDate.Value;

var selectedDates = Enumerable.Range(0, 1 + selectedToDate.Subtract(selectedFromDate).Days)
          .Select(offset => new ReferrerChart { 
                            Date = selectedFromDate.AddDays(offset),
                            LeadsCount = 0,
                            SalesCount = 0
                            })
          .ToList();

var query3 = Find(x => x.Source == "UserRef").AsEnumerable()
             .Where(x => x.Created <= toDate.Value && x.Created >= fromDate.Value)
             .GroupBy(x => x.Created.Date)
             .Select(g => new ReferrerChart {
                 Date = g.Key.Date,
                 LeadsCount = g.Count(x => !x.IsSale),
                 SalesCount = g.Count(x => x.IsSale)
             }).ToList();

var result = query3.Union(
                        selectedDates
                        .Where(e => !query3.Select(x => x.Date).Contains(e.Date)))
                        .OrderBy(x => x.Date);

您可以將查詢中的數據與您在內存中創建的虛擬項進行Union() 例如:

var query4 = query3.ToList(); // Prevent multiple execution.

var startDate = DateTime.Today.AddDays(-99);

var emptyData = Enumerable.Range(1,100).Select (i => 
    new ReferrerChart
        {
           Date = startDate.AddDays(i),
           LeadsCount = 0,
           SalesCount = 0
        });

var result = query4 .Union(
             emptyData
                .Where(e => !query4.Select(x => x.Date).Contains(e.Date)))
             .OrderBy(x => x.Date);

我將在LINQ查詢中更改兩件事,包括空日期

.Where(x => x.Created <= toDate.Value && x.Created >= fromDate.Value)

變成像

.Where(x => x.Created.Date == null || (x.Created <= toDate.Value && x.Created >= fromDate.Value))

我的另一個指針是您的.GroupBy需要一個x.Created.Date,使用IsNull或類似函數將此處的值設置為一個值,而不管條目是否為Null

例如(x.Created == null ? "" : x.Created.ToString("yyyyMMdd"))

(我很抱歉,但是目前我不在開發PC上,因此無法確切說明正確的代碼)

通過實現IEnumerable<IGrouping<TKey, TElement>> (從GroupBy返回的類型)的擴展方法,有一種很棒的方法。 以我的拙見,出於多種原因,這是最好的方法:

  • 不重新計算要填充的結果集( .ToList()也可以完成此操作,但要以急切的評估為代價),
  • 保持對GroupBy惰性評估(延遲執行),
  • 單線友好(可以鏈接到流利的LINQ查詢中),
  • 通用,可重用,
  • 優雅,易於閱讀。

實作

public static IEnumerable<IGrouping<TKey, TElement>> Fill<TKey, TElement>(this IEnumerable<IGrouping<TKey, TElement>> groups, IEnumerable<TKey> filling)
{
    List<TKey> keys = filling.ToList();

    foreach (var g in groups)
    {
        if(keys.Contains(g.Key))
            keys.Remove(g.Key);

        yield return g;
    }

    foreach(var k in keys)
        yield return new EmptyGrouping<TKey, TElement>(k);
}



class EmptyGrouping<TKey, TElement> : List<TElement>, IGrouping<TKey, TElement>
{
    public TKey Key { get; set; }

    public EmptyGrouping(TKey key)
    {
        this.Key = key;
    }
}

樣品用法

Random rand = new Random();

var results = Enumerable.Repeat(0, 5)                    // Give us five
    .Select(i => rand.Next(100))                         // Random numbers 0 - 99
    .GroupBy(r => r.Dump("Calculating group for:") / 10) // Group by tens (0, 10, 20, 30, 40...)
    .Fill(Enumerable.Range(0, 10))                       // Fill aby missing tens
    .OrderBy(g => g.Key);                                // Sort

@"Anything above = eager evaluations.
Anything below = lazy evaluations.".Dump();

results.Dump();

樣品輸出

(在對查詢進行評估時,從查詢內部打印出五個整數。您可以看到,只有一次計算通過)。

填充組實施輸出

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM