C# LINQ(和SQL)通过distinct属性获取最新条目

C# LINQ(和SQL)通过distinct属性获取最新条目,c#,sql,linq,distinct,C#,Sql,Linq,Distinct,我有一个包含以下相关列的表: 机器[钥匙] 样品 实验 已完成日期 。。。我对其执行一些计算的一些测试值 结构 Machine - Sample - Experiment - Completed - ... m1 - s1 - e1 - <date> - ... m1 - s1 - e2 - <date> - ... m1 - s2 - e1 - <

我有一个包含以下相关列的表:

  • 机器[钥匙]
  • 样品
  • 实验
  • 已完成日期
  • 。。。我对其执行一些计算的一些测试值
结构

Machine - Sample - Experiment - Completed - ...
m1      - s1     - e1         - <date>    - ...
m1      - s1     - e2         - <date>    - ...
m1      - s2     - e1         - <date>    - ...
....
m2      - s3     - e1         - <date>    - ...
....
我需要所有标有“*”的行作为我的查询的输出-对于每台机器如此

我甚至在为此编写SQL语句。 如果你知道如何用SQL写这篇文章,请发表,我可能也会从中得到一些东西

编辑:

好的,我再次尝试从下至上,我的第一次尝试是识别最新的5个样本

以下具有固定值的查询有效

var samples = (from c in db.Experiments
           where c.Machine == "m1" 
           orderby c.Completed descending
           select c.Sample).ToList().Distinct().Take(5)
我需要添加“ToList()”,因为Distinct()会把它搞砸

现在,当我将其包含到另一个查询中时,我想要每台机器的结果-它不工作-它不会按完成日期降序排序,而是保持“随机”顺序

为什么会这样

var last5samples = (from t in db.Experiments
                    group t by new { t.Machine } into g
                    select new
                    {
                        Machine = g.Key.Machine,
                        Samples = (from c in db.Experiments
                                   where c.Machine == g.Key.Machine 
                                   orderby c.Completed descending
                                   select c.Sample).ToList().Distinct().Take(5)
                    });
编辑2:

尝试了另一种方法,来登记我真正需要的东西——所有包含最后5个样本的行。 这相当慢,但“起作用”,除了orderby降序不起作用

我首先采用了“IN”方法,但后来发现使用LINQ我需要颠倒逻辑,这就是我的想法:

var last5samples = from t in db.Experiments
                   where (from c in db.Experiments
                          where c.Machine == t.Machine
                          orderby c.Completed descending
                          select c.Sample).ToList().Distinct().Take(5)
                   .Contains(t.Sample)
                   select t;
我现在的主要问题是如何按预期降序工作


我不明白当它是一个单独的查询时为什么它能工作,而当它是一个子查询时,它却不能工作

LINQ没有DistinctBy功能,但幸运的是,有一个名为的库允许您这样做

var results = query.DistinctBy(x => x.Sample).ToList();
使用系统;
使用System.Linq;
使用System.Collections.Generic;
公共课程
{
公共图书馆
{
var list=新列表();
添加(新测试{Machine=“m1”,Sample=“s1”,Experiment=“e1”,DateCompleted=DateTime.Now.AddDays(-2)});
添加(新测试{Machine=“m1”,Sample=“s1”,Experiment=“e1”,DateCompleted=DateTime.Now.AddDays(-1)});
添加(新测试{Machine=“m1”,Sample=“s1”,Experiment=“e1”,DateCompleted=DateTime.Now});
添加(新测试{Machine=“m2”,Sample=“s1”,Experiment=“e1”,DateCompleted=DateTime.Now.AddDays(-2)});
添加(新测试{Machine=“m2”,Sample=“s1”,Experiment=“e1”,DateCompleted=DateTime.Now.AddDays(-1)});
添加(新测试{Machine=“m2”,Sample=“s1”,Experiment=“e1”,DateCompleted=DateTime.Now.AddHours(-1)});
var q=来自列表中的s
按新{s.机器,s.样本}分组s
进入gs
选择新的
{
Machine=gs.Key.Machine
,
Sample=gs.Key.Sample
,
行=gs.OrderByDescending(f=>f.DateCompleted)。取(5)
};
foreach(q.ToList()中的var p)
{
WriteLine(“{0}{1}{2}”,p.Machine,p.Sample,p.Rows.Count());
}
}
}
公开课考试
{
公共字符串计算机{get;set;}
公共字符串样本{get;set;}
公共字符串实验{get;set;}
public DateTime DateCompleted{get;set;}
}

好的,我就是这样解决的

在尝试了我能找到的任何东西之后,我不理解为什么distinct+orderby可以在一种情况下工作(“solo”查询),而不能在另一种情况下工作(subquery),于是我继续按照“我的方式”去做

它的工作速度也足够快(比我最近在编辑2中写的LINQ快)

这是:

  • 我有所有不同的机器
  • 对于每台机器,我取最新的5个样品
  • 对于每台机器,我获取包含最新5个样本的行

    foreach (var m in machines)
    {
    
    var last5Samples = (from t in db.Experiments
                    where t.Machine = m.Machine
                    orderby t.Completed descending
                    select t.Sample).ToList().Distinct().Take(5);
    
    var expsForLast5Samples = from t in db.Experiments
                          where last5Samples.Contains(t.Sample)
                          select t;
    }
    

  • 您需要为distinctBy添加更多信息。您可以参考此线程:对于sql,您需要使用窗口functions@IsThatSo,这里()Jon Skeet提到它只适用于课堂,它不适用于LINQ to SQL。正如@Hazimdekenli-您需要纯SQL中的窗口函数-这通常被认为是一个问题。@dbu没有粗体线条我不确定您是否需要按机器+实验或仅按实验进行分组。我认为这不符合我的需要。请参阅原始帖子中添加的示例。对于每台机器,我需要属于最新5个样本的所有行。@dbu您可以使用此代码,更改分组等。我还更改了查询,以获取每台机器和样本的前5个样本。
    using System;
    using System.Linq;
    using System.Collections.Generic;
    
    
    public class Program
    {
        public void Main()
        {
    
            var list = new List<Test>();
            list.Add(new Test { Machine = "m1", Sample = "s1", Experiment = "e1", DateCompleted = DateTime.Now.AddDays(-2) });
            list.Add(new Test { Machine = "m1", Sample = "s1", Experiment = "e1", DateCompleted = DateTime.Now.AddDays(-1) });
            list.Add(new Test { Machine = "m1", Sample = "s1", Experiment = "e1", DateCompleted = DateTime.Now });
            list.Add(new Test { Machine = "m2", Sample = "s1", Experiment = "e1", DateCompleted = DateTime.Now.AddDays(-2) });
            list.Add(new Test { Machine = "m2", Sample = "s1", Experiment = "e1", DateCompleted = DateTime.Now.AddDays(-1) });
            list.Add(new Test { Machine = "m2", Sample = "s1", Experiment = "e1", DateCompleted = DateTime.Now.AddHours(-1) });
    
            var q = from s in list
                    group s by new { s.Machine, s.Sample }
                        into gs
                        select new
                        {
                            Machine = gs.Key.Machine
                            ,
                            Sample = gs.Key.Sample
                            ,
                            Rows = gs.OrderByDescending(f => f.DateCompleted).Take(5)
                        };
            foreach (var p in q.ToList())
            {
                Console.WriteLine("{0} {1} {2}", p.Machine, p.Sample, p.Rows.Count());
            }
        }
    }
    
    
    
    public class Test
    {
        public string Machine { get; set; }
        public string Sample { get; set; }
        public string Experiment { get; set; }
        public DateTime DateCompleted { get; set; }
    }
    
    foreach (var m in machines)
    {
    
    var last5Samples = (from t in db.Experiments
                    where t.Machine = m.Machine
                    orderby t.Completed descending
                    select t.Sample).ToList().Distinct().Take(5);
    
    var expsForLast5Samples = from t in db.Experiments
                          where last5Samples.Contains(t.Sample)
                          select t;
    }