LINQ to SQL в каждой N-й строке таблицы - PullRequest
15 голосов
/ 17 ноября 2010

Кто-нибудь знает, как написать оператор LINQ to SQL для возврата каждой n-й строки таблицы?Мне нужно вернуть заголовок элемента вверху каждой страницы в разбитой на страницы сетке данных для быстрого сканирования пользователя.Поэтому, если я хотел получить первую запись, то каждую третью после этого под следующими именами:

Эми , Эрик, Джейсон, Джо , Джон, Джош, Марибель , Пол, Стив, Том

Я бы взял Эми, Джо, Марибель и Том.

Я подозреваю, что это можно сделать... Операторы LINQ to SQL уже вызывают функцию SQL ROW_NUMBER () в сочетании с сортировкой и разбиением на страницы.Я просто не знаю, как вернуть каждый n-й предмет.Оператор SQL будет выглядеть примерно так: WHERE ROW_NUMBER MOD 3 = 0, но я не знаю оператора LINQ, который можно использовать для получения правильного SQL.

Ответы [ 6 ]

9 голосов
/ 18 ноября 2010

Иногда 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);
4 голосов
/ 18 ноября 2010

Давным-давно не было такого понятия, как Row_Number, и все же такие запросы были возможны.Вот!

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 голосов
/ 18 ноября 2010

Вот вариант, который работает, но, возможно, стоит проверить, что на практике у него нет проблем с производительностью:

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));
1 голос
/ 18 ноября 2010

Это поможет, но это не самый эффективный запрос в мире:

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 и т. Д.) Из данного запроса. Если вы используете эту технику, вы, вероятно, захотите создать ограничение в десять или двадцать имен, аналогично тому, как страница результатов Google (1-10 и далее), чтобы избежать получения такого большого выражения, база данных отказывается попытаться разобрать его.

Если вам нужна более высокая производительность, вам, вероятно, придется использовать хранимую процедуру или представление для представления вашего запроса и включать номер строки как часть сохраненных результатов процесса или полей представления.

1 голос
/ 17 ноября 2010

Просто немного погуглив, я не нашел (или не испытал) вариант, чтобы Linq to SQL напрямую поддерживал это.

Единственный вариант, который я могу предложить, - это написать хранимую процедуру с соответствующим написанным SQL-запросом и затем вызвать sproc через Linq to SQL. Не лучшее решение, особенно если у вас есть какая-либо сложная фильтрация.

1 голос
/ 17 ноября 2010

На самом деле, кажется, нет простого способа сделать это:

Как добавить ROW_NUMBER в запрос или объект LINQ?

Как найти ROW_NUMBER () строки с Linq to SQL

Но всегда есть:

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

ПРИМЕЧАНИЕ: Это по-прежнему не выполняется на стороне базы данных!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...