SQL:Linq - 列值更改的不同行

时间:2014-04-09 13:50:10

标签: c# sql database linq

如何在LINQ中创建一个过滤器,其中查询仅将两个后续行组合在一起,如果它们的Level列由一个列提升。

这就是我现在所拥有的:

var alert = db.Logs.OrderBy(u => u.Time).GroupBy(r => r.EquipmentNr).Where(s => s.Count() > 1);

然而,它不会找到那些在Level列中不同的行,并且它们必须随着时间的推移而不同。必须有彼此相邻的行,按时间排序。

或者我应该手动创建分组类,运行我已经拥有的查询并添加是否找到它们?

public class Log
{
    public int Id { get; set; }
    public DateTime Time { get; set; }
    public Shift Shift { get; set; }
    public int EquipmentNr { get; set; }
    public int OrderNr { get; set; }
    public bool SupervisorCalled { get; set; }
    public string Issue { get; set; }
    public string Repairs { get; set; }
    public string Responsible { get; set; }
    public Level Level { get; set; }
}

1 个答案:

答案 0 :(得分:0)

大多数情况下,对于顺序处理,列表中的元素以某种方式相关,经典foreach比LINQ好得多。通常它甚至不能由LINQ完成。但是,在这种情况下,只需要比较连续的元素,因此可以使用Aggregate

分组条件是:level(n) - level(n-1) = 1。因此,我们应该为满足此条件的列表中的每个元素添加相同的分组键。这是一种方法(使用Linqpad)。每个元素都存储在Tuple中,其中Item1是分组键。然后按这些键对元组进行分组:

void Main()
{
    var list = new List<Equipment>
    { 
    new Equipment{Level = 11},
    new Equipment{Level = 1},
    new Equipment{Level = 18},
    new Equipment{Level = 0},
    new Equipment{Level = 6},
    new Equipment{Level = 4},
    new Equipment{Level = 5},
    new Equipment{Level = 20},
    new Equipment{Level = 9},
    new Equipment{Level = 14},
    new Equipment{Level = 12},
    new Equipment{Level = 17},
    new Equipment{Level = 2},
    new Equipment{Level = 13},
    new Equipment{Level = 15},
    };
    list.OrderBy(eq => eq.Level)
        .Aggregate
        (
            new List<Tuple<int,Equipment>>(), // Seed the list of tuples
            (tuples,eq) =>
            {
                // The grouping condition: compare to the previous item
                // (if present) and use its Level as grouping key if the
                // condition is met.
                var key = tuples.Any() 
                            && eq.Level - tuples.Last().Item2.Level == 1
                        ? tuples.Last().Item1
                        : eq.Level; 
                tuples.Add(Tuple.Create(key, eq)); 
                return tuples;
            }, 
            tuples => tuples.GroupBy (tuple => tuple.Item1)
        // Done! Now just a Select for display
        ).Select
        (tupleGroup =>
            new { 
                    tupleGroup.Key,
                    Numbers = string.Join(",", tupleGroup
                                               .Select(e => e.Item2.Level))
                }
        ). Dump();

}

// Define other methods and classes here
class Equipment
{
    public int Level { get; set; }
}

输出:

Key  Numbers 
---  --------------
0    0,1,2 
4    4,5,6 
9    9 
11   11,12,13,14,15 
17   17,18 
20   20