【问题标题】:LINQ (and SQL) to get latest entries by distinct propertyLINQ(和 SQL)通过不同的属性获取最新条目
【发布时间】:2014-12-03 11:07:24
【问题描述】:

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

  • 机器 [钥匙]
  • 示例
  • 实验
  • 完成日期
  • ...我执行一些计算的一些测试值

结构

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

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

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

一旦我按 Machine 分组并按 DateCompleted 降序排序,我似乎找不到下一步。

我猜想某种“DistinctBy (x => 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 个样本。 这很慢,但是“工作”,有点,除了 orderby descending 不起作用。

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

我现在的主要问题是如何按预期进行降序排序。

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

【问题讨论】:

标签: c# sql linq distinct


【解决方案1】:

LINQ 没有DistinctBy 功能,但幸运的是有一个名为morelinq 的库可以让您做到这一点。

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

【讨论】:

    【解决方案2】:
    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; }
    }
    

    【讨论】:

    • 我不确定您是否需要按机器+实验分组,还是仅按实验分组。
    • 我认为这不能满足我的需要。请参阅原始帖子中添加的示例。对于每台机器,我需要属于最新 5 个样本的所有行。
    • @dbu 您可以使用此代码,更改分组等。我还更改了查询以获取每台机器和样本的前 5 个样本。
    【解决方案3】:

    好的,我就是这样解决的。

    在尝试了我能找到的任何东西之后,不明白为什么 distinct + orderby 在一种情况下(“solo”查询)而不是另一种情况下(“子查询”)起作用,我继续以“我的方式”去做。

    它的运行速度也足够快(比我最近在 EDIT 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;
      }
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-21
      • 2020-11-04
      • 2012-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多