使用LINQ to Entities选择连续的条目

时间:2010-11-27 20:50:20

标签: database linq linq-to-entities

我有一个包含行的数据库表,每行包含一个顺序索引。我想根据此索引列选择连续的行组。例如,如果我的行包含以下索引值:

1
3
4
5
7
9
10
11
12
15
16

我希望选择所有具有3个连续索引的组(此数字会有所不同)。我会得到以下几组:

3, 4, 5

9, 10, 11

10, 11, 12

基本上,我正在努力实现类似于此处提出的问题:

selecting consecutive numbers using SQL query

但是,我想用LINQ to Entities实现它,而不是实际的SQL。我也不想使用存储过程,我不想做任何类型的ToList /循环方法。

编辑:具有多个请求的连续元素的组不一定需要拆分。即在前面的例子中,9,10,11,12的结果也是可以接受的。

4 个答案:

答案 0 :(得分:1)

所以我认为我已经提出了一个非常好的解决方案,模仿Brian在我链接的主题中的回答。

var q = from a in query
        from b in query
        where a.Index < b.Index
        && b.Index < a.Index + 3
        group b by new { a.Index }
            into myGroup
            where myGroup.Count() + 1 == 3
            select myGroup.Key.Index;

将3更改为所需的连续行数。这为您提供了每组连续行的第一个索引。应用于我提供的原始示例,您将获得:

3
9
10

答案 1 :(得分:1)

我认为这可能非常有效(C#):

int[] query = { 1, 3, 4, 5, 7, 9, 10, 11, 12, 15, 16 };
int count = 3;
List<List<int>> numbers = query
   .Where(p => query.Where(q => q >= p && q < p + count).Count() == count)
   .Select(p => Enumerable.Range(p, count).ToList())
   .ToList();

答案 2 :(得分:0)

using (var model = new AlbinTestEntities())
{
    var triples = from t1 in model.Numbers
                  from t2 in model.Numbers
                  from t3 in model.Numbers
                  where t1.Number + 1 == t2.Number
                  where t2.Number + 1 == t3.Number
                  select new
                  {
                      t1 = t1.Number,
                      t2 = t2.Number,
                      t3 = t3.Number,
                  };

    foreach (var res in triples)
    {
        Console.WriteLine(res.t1 + ", " + res.t2 + ", " + res.t3);
    }
}

它生成以下SQL

SELECT 
[Extent1].[Number] AS [Number], 
[Extent2].[Number] AS [Number1], 
[Extent3].[Number] AS [Number2]
FROM   [dbo].[Numbers] AS [Extent1]
CROSS JOIN [dbo].[Numbers] AS [Extent2]
CROSS JOIN [dbo].[Numbers] AS [Extent3]
WHERE (([Extent1].[Number] + 1) = [Extent2].[Number]) AND (([Extent2].[Number] + 1) = [Extent3].[Number])

使用像这样的内连接可能更好

using (var model = new AlbinTestEntities())
{
    var triples = from t1 in model.Numbers
                  join t2 in model.Numbers on t1.Number + 1 equals t2.Number
                  join t3 in model.Numbers on t2.Number + 1 equals t3.Number
                  select new
                  {
                      t1 = t1.Number,
                      t2 = t2.Number,
                      t3 = t3.Number,
                  };

    foreach (var res in triples)
    {
        Console.WriteLine(res.t1 + ", " + res.t2 + ", " + res.t3);
    }
}

但是当我在管理工作室中比较结果查询时,它们会生成相同的执行计划,并执行完全相同的时间。我只有这个有限的数据集,你可以比较你的数据集的性能,如果它更大,并选择最好的,如果它们不同。

答案 3 :(得分:0)

以下代码将找到每个“root”。

    var query = this.commercialRepository.GetQuery();
    var count = 2;
    for (int i = 0; i < count; i++)
    {
        query = query.Join(query, outer => outer.Index + 1, inner => inner.Index, (outer, inner) => outer);
    }

    var dummy = query.ToList();

它只会找到每个组中的第一个项目,因此您必须修改查询以记住其他项目,或者您可以根据您拥有根的事实和您知道的哪些索引来进行查询。得到。对不起,我不得不把它包起来,但也许它有点帮助。

PS。如果count为2,就像在这种情况下,它意味着如果找到3的组。