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

时间:2014-12-03 11:07:24

标签: c# sql linq distinct

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

  • 机器[Key]
  • 样品
  • 实验
  • DateCompleted
  • ...我执行某些计算的一些测试值

结构

Machine - Sample - Experiment - Completed - ...
m1      - s1     - e1         - <date>    - ...
m1      - s1     - e2         - <date>    - ...
m1      - s2     - e1         - <date>    - ...
....
m2      - s3     - e1         - <date>    - ...
....

在每台机器上,可以对单个样品执行多个实验。

我的目标是识别每台机器的 5个最新-distinct-样本,并获得所有相关条目(整行,包括此示例中的所有实验)。< / p>

一旦我按照机器分组并按DateCompleted降序排序,我似乎无法找到下一步。

我想某种“DistinctBy(x =&gt; x.Sample)”是必需的,但是无法解决这个问题。

实施例: (按日期顺序递减)

Machine - Sample - Experiment
m1 - s1 - e1 * 
m1 - s1 - e2 *
m1 - s2 - e1 *
m1 - s2 - e2 *
m1 - s3 - e1 *
m1 - s4 - e1 *
m1 - s4 - e2 *
m1 - s5 - e1 *
m1 - s6 - e1
m1 - s6 - e2
...

我需要标记为“*”的所有行作为我的查询的输出 - 对于每台机器都是如此。

我正在努力为此编写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个样本的所有行。 这很慢,但“有效”,除了命令降序不起作用。

我首先使用“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;

我现在的主要问题是如何按预期降序工作。

我不明白为什么它在单独查询时有效,而在子查询时则不然。

3 个答案:

答案 0 :(得分:0)

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

var results = query.DistinctBy(x => x.Sample).ToList();

答案 1 :(得分:0)

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; }
}

答案 2 :(得分:0)

好的,这就是我解决它的方法。

在尝试了我能找到的任何东西之后,并且不理解为什么distinct + orderby在一个案例中工作(&#34; solo&#34;查询)而不是另一个(子查询),我接着去做了#34; my方式&#34;

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

这是:

  1. 我得到所有不同的机器
  2. 对于每台机器,我都会获取最新的5个样本
  3. 对于每台机器,我都会获取包含最新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;
    }