C# 为每种类型选择最新项目

C# 为每种类型选择最新项目,c#,entity-framework,C#,Entity Framework,这是基于托迪洛以前的一份报告 以下被接受的答案非常有效,除了每个类型的最新记录外,我还需要返回类型为null的所有记录: var query = Posts.GroupBy(p => p.Type) .Select(g => g.OrderByDescending(p => p.Date) .FirstOrDefault() ) 情况如下: +----+-----

这是基于托迪洛以前的一份报告

以下被接受的答案非常有效,除了每个类型的最新记录外,我还需要返回类型为null的所有记录:

var query = Posts.GroupBy(p => p.Type)
              .Select(g => g.OrderByDescending(p => p.Date)
                            .FirstOrDefault()
               )
情况如下:

+----+--------------------------+-------+------------+
| id |         content          | type  |    date    |
+----+--------------------------+-------+------------+
|  0 | Some text                | TypeA | 2013-04-01 |
|  1 | Some older text          | TypeA | 2012-03-01 |
|  2 | Some even older texttext | TypeA | 2011-01-01 |
|  3 | Sample                   |       | 2013-02-24 |
|  4 | A dog                    | TypeB | 2013-04-01 |
|  5 | And older dog            | TypeB | 2012-03-01 |
|  6 | An even older dog        | TypeB | 2011-01-01 |
|  7 | Another sample           |       | 2014-03-06 |
|  8 | Test                     |       | 2015-11-08 |
+----+--------------------------+-------+------------+
结果应该是

Some text      | TypeA
Sample         |
A dog          | TypeB
Another sample |
Test           |
那么:

var query = Posts
              .GroupBy(p => p.Type)
              .Select(g => g.OrderByDescending(p => p.Date).FirstOrDefault()).ToList()
var lostNullItems = Posts.Where(p => p.Type == null && !query.Contains(p));
var newQuery = query.Union(lostNullItems);
如果您不需要可以使用的项目的顺序:

var query = Posts
              .GroupBy(p => p.Type)
              .SelectMany(g => 
                   {
                      var result = g.OrderByDescending(p => p.Date);
                      return g.Key == null ? result ? Enumerable.Repeat(result.First(), 1);
                   });
这段代码没有经过测试。

那怎么办:

var query = Posts
              .GroupBy(p => p.Type)
              .Select(g => g.OrderByDescending(p => p.Date).FirstOrDefault()).ToList()
var lostNullItems = Posts.Where(p => p.Type == null && !query.Contains(p));
var newQuery = query.Union(lostNullItems);
如果您不需要可以使用的项目的顺序:

var query = Posts
              .GroupBy(p => p.Type)
              .SelectMany(g => 
                   {
                      var result = g.OrderByDescending(p => p.Date);
                      return g.Key == null ? result ? Enumerable.Repeat(result.First(), 1);
                   });

此代码未经测试。

请尝试下面的代码。由于分组的原因,顺序不同

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;


namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

            DataTable dt = new DataTable();
            dt.Columns.Add("id", typeof(int));
            dt.Columns.Add("content", typeof(string));
            dt.Columns.Add("type", typeof(string));
            dt.Columns["type"].AllowDBNull = true;
            dt.Columns.Add("date", typeof(DateTime));

            dt.Rows.Add(new object[] { 0, "Some text", "TypeA", DateTime.Parse("2013-04-01")});
            dt.Rows.Add(new object[] { 1, "Some older text", "TypeA", DateTime.Parse("2012-03-01")});
            dt.Rows.Add(new object[] { 2, "Some older texttext", "TypeA", DateTime.Parse("2011-01-01")});
            dt.Rows.Add(new object[] { 3, "Sample", null, DateTime.Parse("2013-02-24")});
            dt.Rows.Add(new object[] { 3, "A dog", "TypeB", DateTime.Parse("2013-04-01")});
            dt.Rows.Add(new object[] { 4, "And older dog", "TypeB", DateTime.Parse("2012-03-01")});
            dt.Rows.Add(new object[] { 5, "An even older dog", "TypeB", DateTime.Parse("2011-01-01")});
            dt.Rows.Add(new object[] { 4, "Another sample", null, DateTime.Parse("2014-03-06")});
            dt.Rows.Add(new object[] { 5, "Test", null, DateTime.Parse("2015-11-08")});

            var results = dt.AsEnumerable()
                .GroupBy(x => x.Field<string>("type"))
                .Select(x => x.Key == null ? x.ToList() : x.Select(y => new {date = y.Field<DateTime>("date"), row = y}).OrderByDescending(z => z.date).Select(a => a.row).Take(1))
                .SelectMany(b => b).Select(c => new {
                    content = c.Field<string>("content"), 
                    type = c.Field<string>("type") 
                }).ToList();


        }
    }
}
​
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用系统数据;
命名空间控制台应用程序1
{
班级计划
{
静态void Main(字符串[]参数)
{
DataTable dt=新的DataTable();
添加(“id”,typeof(int));
添加(“内容”,类型(字符串));
添加(“类型”,类型(字符串));
dt.列[“类型”]。AllowDBNull=true;
添加(“日期”,类型(日期时间));
Add(新对象[]{0,“一些文本”,“TypeA”,DateTime.Parse(“2013-04-01”)});
Add(新对象[]{1,“一些旧文本”,“TypeA”,DateTime.Parse(“2012-03-01”)});
Add(新对象[]{2,“一些旧文本”,“TypeA”,DateTime.Parse(“2011-01-01”)});
Add(新对象[]{3,“Sample”,null,DateTime.Parse(“2013-02-24”)});
Add(新对象[]{3,“一只狗”,“TypeB”,DateTime.Parse(“2013-04-01”)});
Add(新对象[]{4,“和老狗”,“TypeB”,DateTime.Parse(“2012-03-01”)});
Add(新对象[]{5,“一只更老的狗”,“TypeB”,DateTime.Parse(“2011-01-01”)});
Add(新对象[]{4,“另一个示例”,null,DateTime.Parse(“2014-03-06”)});
Add(新对象[]{5,“Test”,null,DateTime.Parse(“2015-11-08”)});
var结果=dt.AsEnumerable()
.GroupBy(x=>x.Field(“类型”))
.Select(x=>x.Key==null?x.ToList():x.Select(y=>new{date=y.Field(“date”),row=y}).OrderByDescending(z=>z.date).选择(a=>a.row).Take(1))
.SelectMany(b=>b)。选择(c=>new){
内容=c.字段(“内容”),
类型=c.字段(“类型”)
}).ToList();
}
}
}
​

尝试下面的代码。由于分组的原因,顺序不同

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;


namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

            DataTable dt = new DataTable();
            dt.Columns.Add("id", typeof(int));
            dt.Columns.Add("content", typeof(string));
            dt.Columns.Add("type", typeof(string));
            dt.Columns["type"].AllowDBNull = true;
            dt.Columns.Add("date", typeof(DateTime));

            dt.Rows.Add(new object[] { 0, "Some text", "TypeA", DateTime.Parse("2013-04-01")});
            dt.Rows.Add(new object[] { 1, "Some older text", "TypeA", DateTime.Parse("2012-03-01")});
            dt.Rows.Add(new object[] { 2, "Some older texttext", "TypeA", DateTime.Parse("2011-01-01")});
            dt.Rows.Add(new object[] { 3, "Sample", null, DateTime.Parse("2013-02-24")});
            dt.Rows.Add(new object[] { 3, "A dog", "TypeB", DateTime.Parse("2013-04-01")});
            dt.Rows.Add(new object[] { 4, "And older dog", "TypeB", DateTime.Parse("2012-03-01")});
            dt.Rows.Add(new object[] { 5, "An even older dog", "TypeB", DateTime.Parse("2011-01-01")});
            dt.Rows.Add(new object[] { 4, "Another sample", null, DateTime.Parse("2014-03-06")});
            dt.Rows.Add(new object[] { 5, "Test", null, DateTime.Parse("2015-11-08")});

            var results = dt.AsEnumerable()
                .GroupBy(x => x.Field<string>("type"))
                .Select(x => x.Key == null ? x.ToList() : x.Select(y => new {date = y.Field<DateTime>("date"), row = y}).OrderByDescending(z => z.date).Select(a => a.row).Take(1))
                .SelectMany(b => b).Select(c => new {
                    content = c.Field<string>("content"), 
                    type = c.Field<string>("type") 
                }).ToList();


        }
    }
}
​
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用系统数据;
命名空间控制台应用程序1
{
班级计划
{
静态void Main(字符串[]参数)
{
DataTable dt=新的DataTable();
添加(“id”,typeof(int));
添加(“内容”,类型(字符串));
添加(“类型”,类型(字符串));
dt.列[“类型”]。AllowDBNull=true;
添加(“日期”,类型(日期时间));
Add(新对象[]{0,“一些文本”,“TypeA”,DateTime.Parse(“2013-04-01”)});
Add(新对象[]{1,“一些旧文本”,“TypeA”,DateTime.Parse(“2012-03-01”)});
Add(新对象[]{2,“一些旧文本”,“TypeA”,DateTime.Parse(“2011-01-01”)});
Add(新对象[]{3,“Sample”,null,DateTime.Parse(“2013-02-24”)});
Add(新对象[]{3,“一只狗”,“TypeB”,DateTime.Parse(“2013-04-01”)});
Add(新对象[]{4,“和老狗”,“TypeB”,DateTime.Parse(“2012-03-01”)});
Add(新对象[]{5,“一只更老的狗”,“TypeB”,DateTime.Parse(“2011-01-01”)});
Add(新对象[]{4,“另一个示例”,null,DateTime.Parse(“2014-03-06”)});
Add(新对象[]{5,“Test”,null,DateTime.Parse(“2015-11-08”)});
var结果=dt.AsEnumerable()
.GroupBy(x=>x.Field(“类型”))
.Select(x=>x.Key==null?x.ToList():x.Select(y=>new{date=y.Field(“date”),row=y}).OrderByDescending(z=>z.date).选择(a=>a.row).Take(1))
.SelectMany(b=>b)。选择(c=>new){
内容=c.字段(“内容”),
类型=c.字段(“类型”)
}).ToList();
}
}
}
​

我认为LINQ
联合是实现这一点的唯一方法,主要是因为您是如何按日期对输出进行排序的

第一个查询应如下所示:

var nullTypes = from p in Posts
                     where p.Type == null
                     select p;
主查询应该只过滤掉空值:

var query = Posts.Where(p => p.Type != null).GroupBy(p => p.Type)
          .Select(g => g.OrderByDescending(p => p.Date)
                        .FirstOrDefault()
           )
与主查询的联合:

var unionQuery = query.Union(nullTypes).OrderBy(p => p.Date);
输出将符合您的期望,只是前两行按顺序颠倒:

Sample | Some text | TypeA A dog | TypeB Another sample | Test | 样品| 一些文本| TypeA B型狗 另一个样本| 试验| 这是因为包含“Sample”的行项目的日期比“Some text”的日期早


您不需要执行任何
SelectMany
-原始的
Select
将投影一个项目,因此这将生成一个适合联合体的IEnumerable。

我认为LINQ
联合体
是执行此操作的唯一方法,主要是因为您是如何按日期对输出进行排序的

第一个查询应如下所示:

var nullTypes = from p in Posts
                     where p.Type == null
                     select p;
主查询应该只过滤掉空值:

var query = Posts.Where(p => p.Type != null).GroupBy(p => p.Type)
          .Select(g => g.OrderByDescending(p => p.Date)
                        .FirstOrDefault()
           )
与主查询的联合:

var unionQuery = query.Union(nullTypes).OrderBy(p => p.Date);
输出将符合您的期望,只是前两行按顺序颠倒:

Sample | Some text | TypeA A dog | TypeB Another sample | Test | 样品| 一些文本| TypeA B型狗 另一个样本| 试验| 这是因为包含“Sample”的行项目的日期比“Some text”的日期早


您不需要执行任何
SelectMany
-原始的
Select
将投影一个项目,因此这将成为一个可以适应该联合的IEnumerable。

我只能将其视为LINQ联合。我只能