2015-07-21 69 views
3

我有一个场景,我的数据看起来像这样。获取第一个项目和最后一个项目,如果它存在于一个组中

 
Books 
--------------------------------- 
title   | returnedDate 
Great Gatsby  | 2015-05-04 
Great Gatsby  | 2015-03-22 
Great Gatsby  | 2015-01-11 
Life of PI  | 2015-04-04 
Life of PI  | 2015-04-02 
Clean Code  | 2015-06-05 

我想每个组返回最先和最后一本书(按标题分类)在一个单一的LINQ语句。我知道我可以用这样的linq查询来获得第一个或最后一个项目。

var books = dbContext.Books 
    .GroupBy(b => b.title) 
    .Select(g => g.OrderDescending().FirstOrDefault()); 

如果存在最后一项,我该如何获得?

我最终的结果会是什么样子:

 
Books 
--------------------------------- 
title   | returnedDate 
Great Gatsby  | 2015-05-04 
Great Gatsby  | 2015-01-11 
Life of PI  | 2015-04-04 
Life of PI  | 2015-04-02 
Clean Code  | 2015-06-05 

回答

0

随着一些摆弄,我想出了这个。不知道在处理大量数据表时这将会有多高效。

 [Test] 
    public void FirstLastLinq() 
    { 
     var books = new List<Book> 
     { 
      new Book { Title = "Great Gatsby", Returned=new DateTime(2015,04,03) }, 
      new Book { Title = "Great Gatsby", Returned=new DateTime(2015,04,02) }, 
      new Book { Title = "Great Gatsby", Returned=new DateTime(2015,04,01) }, 
      new Book { Title = "Life of PI", Returned=new DateTime(2015,03,05) }, 
      new Book { Title = "Life of PI", Returned=new DateTime(2015,03,04) }, 
      new Book { Title = "Clean Code", Returned=new DateTime(2015,02,02) }, 
     }; 

     var newBooks = books.GroupBy(b => b.Title).SelectMany(g => g.OrderByDescending(b => b.Returned) 
      .Where(b1 => b1.Returned == g.Min(b2 => b2.Returned) || 
       (b1.Returned == g.Max(b3 => b3.Returned) && g.Min(b4 => b4.Returned) != g.Max(b5 => b5.Returned)))); 

     Assert.IsNotNull(newBooks); 

    } 
    private class Book 
    { 
     public string Title { get; set; } 
     public DateTime Returned { get; set; } 
    } 
3
var books = dbContext.Books 
    .GroupBy(b => b.title) 
    .Select(g=>new { 
     Title=g.Key, 
     First=g.OrderByDescending(x=>x).FirstOrDefault(), 
     Last=g.OrderBy(x=>x).FirstOrDefault() 
    }); 

Results: 
title     | First | Last 
Great Gatsby | 2015-05-04 | 2015-01-11 
Life of PI   | 2015-04-04 | 2015-04-02 
Clean Code | 2015-06-05 | 2015-06-05 

如果你真的想它就像你问的话,那就有点困难:

var books = dbContext.Books 
    .GroupBy(b => b.title) 
    .Select(g=>new { 
     title=g.Key, 
     returnedDate=g.OrderByDescending(x=>x).FirstOrDefault() 
    }).Concat(
     dbContext.Books 
     .GroupBy(b => b.title) 
     .Where(g=>g.Count()>1) 
     .Select(g=>new { 
     title=g.Key, 
     returnedDate=g.OrderBy(x=>x).FirstOrDefault() 
     }) 
    ).OrderBy(c=>c.title).ThenDescendingBy(c=>c.returnedDate); 

呸。可能是更好的方法,但首先想到的。

+0

哎哟,看起来很吓人。无论如何感谢您的答案。 – Andrew

2

有可能通过获得第一和最后的返回日期,然后返回的书籍,归还日期是等于这些:

from b in dbContext.Books 
group b by b.title into bg 
let first = bg.OrderByDescending (b => b.returnedDate).FirstOrDefault().returnedDate 
let last = bg.OrderBy (b => b.returnedDate).FirstOrDefault().returnedDate 
from b in bg 
where b.returnedDate == first || b.returnedDate == last 
orderby b.title, b.returnedDate 
select b 
+0

感谢Gert的建议。我想返回原始Book对象而不是匿名对象 – Andrew

+1

Easy。查看编辑。 –

相关问题