代码之家  ›  专栏  ›  技术社区  ›  bopapa_1979

表中每N行的Linq to SQL

  •  15
  • bopapa_1979  · 技术社区  · 14 年前

    有人知道如何编写LINQ to SQL语句来返回表中的每N行吗?我需要在页面数据网格的每个页面的顶部获取项目的标题,以便用户快速扫描。所以,如果我想要第一张唱片,那么每三张之后,从下面的名字开始:

    艾米 埃里克,杰森, 约翰,乔希, 玛丽贝尔 保罗,史蒂夫, 汤姆

    我去找艾米、乔、玛丽贝尔和汤姆。

    我怀疑这是可以做到的…linq to sql语句已经结合排序和分页调用row_number()sql函数。我就是不知道怎么把每件东西都拿回来。SQL语句应该是 WHERE ROW_NUMBER MOD 3 = 0 但我不知道要使用LINQ语句来获取正确的SQL。

    6 回复  |  直到 14 年前
        1
  •  9
  •   Marc Gravell    14 年前

    有时候,TSQL是一个不错的选择。我会用 ExecuteQuery<T> 在这里:

        var data = db.ExecuteQuery<SomeObjectType>(@"
    SELECT * FROM 
    (SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS [__row]
    FROM [YourTable]) x WHERE (x.__row % 25) = 1");
    

    你也可以换掉 n :

        var data = db.ExecuteQuery<SomeObjectType>(@"
    DECLARE @n int = 2
    SELECT * FROM 
    (SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS [__row]
    FROM [YourTable]) x WHERE (x.__row % @n) = 1", n);
    
        2
  •  4
  •   Amy B    14 年前

    从前,没有行号这样的东西,但是这样的查询是可能的。看到!

    var query =
      from c in db.Customers
      let i = (
        from c2 in db.Customers
        where c2.ID < c.ID
        select c2).Count()
      where i%3 == 0
      select c;
    

    这将生成以下SQL

    SELECT [t2].[ID], [t2]. --(more fields)
    FROM (
        SELECT [t0].[ID], [t0]. --(more fields)
    (
            SELECT COUNT(*)
            FROM [dbo].[Customer] AS [t1]
            WHERE [t1].[ID] < [t0].[ID]
            ) AS [value]
        FROM [dbo].[Customer] AS [t0]
        ) AS [t2]
    WHERE ([t2].[value] % @p0) = @p1
    
        3
  •  3
  •   Enigmativity    14 年前

    这里有一个可行的选项,但在实践中可能值得检查它是否没有任何性能问题:

    var nth = 3;
    var ids = Table
                .Select(x => x.Id)
                .ToArray()
                .Where((x, n) => n % nth == 0)
                .ToArray();
    
    var nthRecords = Table
                       .Where(x => ids.Contains(x.Id));
    
        4
  •  1
  •   Chris Shaffer    14 年前

    只是在谷歌上搜索一下,我还没有找到(或体验过)LinqToSQL直接支持这个选项。

    我能提供的唯一选项是编写一个存储过程,并写出适当的SQL查询,然后通过linq to sql调用存储过程。不是最好的解决方案,尤其是在进行任何复杂的过滤时。

        5
  •  1
  •   Community paulsm4    7 年前

    这样做似乎并不容易:

    How do I add ROW_NUMBER to a LINQ query or Entity?

    How to find the ROW_NUMBER() of a row with Linq to SQL

    但总有:

    peopleToFilter.AsEnumerable().Where((x,i) => i % AmountToSkipBy == 0)
    

    注: 这仍然不能在数据库端执行!

        6
  •  1
  •   StriplingWarrior    14 年前

    这将起到关键作用,但它不是世界上最有效的查询:

    var count = query.Count();
    var pageSize = 10;
    var pageTops = query.Take(1);
    for(int i = pageSize; i < count; i += pageSize)
    {
        pageTops = pageTops.Concat(query.Skip(i - (i % pageSize)).Take(1));
    }
    return pageTops;
    

    它动态构造一个查询,从给定的查询中提取(nth、2*nth、3*nth等)值。如果您使用这种技术,您可能希望创建一个大约10个或20个名称的限制,类似于Google结果页面(1-10,下一个)的限制,以避免得到如此大的表达式,数据库拒绝尝试解析它。

    如果需要更好的性能,可能需要使用存储过程或视图来表示查询,并将行数作为存储过程结果或视图字段的一部分包括在内。