簡體   English   中英

如何避免查詢 linq 中的 OrderByDescending

[英]How to avoid OrderByDescending in query linq

我有 linq 查詢:

var ed = db.table
.GroupBy(x => x.Sn)
.Select(g => g.OrderByDescending(x => x.Date).FirstOrDefault());

我需要重寫此查詢以進行服務器端評估。

我的桌子:

Sn    Value      Data     
150   180.3    01/06/2020  
150   195.0    01/05/2020  
149   13.3     01/06/2020  
345   27.5     27/06/2013
....  
.Select(g => g.OrderByDescending(x => x.Date).FirstOrDefault())

可能只是:

.Select(g => g.Max(x => x.Date))

解析器可能處理得更好

您可以嘗試使用Aggregate

var ed = db.table
           .GroupBy(x => x.Sn)
           .Select(x => x.Aggregate((max, cur) => max.Date > cur.Date ? max : cur));

這可能會幫助您了解更多如何使用 LINQ 到 select object 與最小或最大屬性值

這取決於dt.Table是否為 IQueryable。

通常 IQueryable 將由不同的進程執行,通常是數據庫管理系統。 在這種情況下,您必須使用 OrderBy 后跟 FirstOrDefault。

幸運的是,適當的數據庫管理系統已針對排序進行了極大優化。 如果您對排序的效率不滿意,並且您不經常更改表,請考慮在 DbContext.OnModelCreating 中添加一個額外的索引:

modelBuilder.Entity<Customer>()
    .HasIndex(customer => customer.Name)

您的數據庫管理系統知道這個額外的索引,並且可以立即返回索引的最后一項所引用的元素。

每當您更改名稱或添加新客戶時,都必須重新創建索引。 因此,如果您經常更改客戶名稱,例如每秒 10 次,請不要這樣做。

如果dt.table不是IQueryable,而是IEnumerable,OrderBy比較慢。 唉,沒有 Enumerable.Max 適合您,但您可以使用Enumerable.Aggregate的重載。

由於您確定每個組至少包含一個元素,因此您可以使用不帶 Seed 的重載:

var result = db.table.GroupBy(x => x.Sn)
   .Aggregate( (maxItem, nextitem) =>(nextItem.Date > maxItem.Date) ?? nextItem : maxItem)

如果您經常使用它,請考慮創建一個擴展方法。 創建擴展方法非常容易。 請參閱揭秘的擴展方法

public static T MaxOrDefault<T, TProperty> MaxPropertyOrDefault(
    this IEnumerable<T> source,
    Func<TSource, TProperty> propertySelector)
{
     return MaxPropertyOrDefault(source, propertySelector, null)
}

比較器重載:如果比較器等於 null,則使用默認比較器

public static T MaxOrDefault<T, TProperty> MaxPropertyOrDefault(
    this IEnumerable<T> source,
    Func<TSource, TProperty> propertySelector,
    IComparer<TProperty) comparer)
{
    // TODO: what to do if source == null?
    // TODO: what to do if propertySelector == null?
    if (comparer == null) comparer = Comparer<TProperty>.Default();
    
    var enumerator = source.GetEnumerator();
    if (!enumerator.MoveNext)
    {
        // empty source, return default:
        return default(T);
    }
    else
    {
        TProperty maxPropertyValue = propertySelector(enumerator.Current);
        T maxValue = enumerator.Current();

        while (enumerator.MoveNext())
        {
             TProperty currentPropertyValue = propertySelector(enumerator.Current);
             if (comparer.Compare(currentPropetyValue, maxPropertyValue) > 0)
             {
                 maxPropertyValue = currentPropertyValue;
                 maxValue = enumerator.Current;
             } 
        }
        return maxValue;
    }
}

用法:

var ed = db.table.GroupBy(x => x.Sn)
           .Select(group => group.MaxOrDefault(groupElement => groupElement.Date);

暫無
暫無

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

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