Подтвердить что ты не робот

Используя Linq to SQL, как мне найти min и max столбца в таблице?

Я хочу найти самый быстрый способ получить минимальный и максимальный столбцы в таблице с одним обратным вызовом Linq to SQL. Поэтому я знаю, что это будет работать в двух раундах:

int min = MyTable.Min(row => row.FavoriteNumber);
int max = MyTable.Max(row => row.FavoriteNumber);

Я знаю, что могу использовать group, но у меня нет предложения group by, я хочу агрегировать по всей таблице! И я не могу использовать .Min без группировки в первую очередь. Я попробовал это:

from row in MyTable 
group row by true into r 
select new { 
    min = r.Min(z => z.FavoriteNumber), 
    max = r.Max(z => z.FavoriteNumber) 
}

Но это сумасшедшее предложение группы кажется глупым, а SQL-код более сложный, чем это должно быть.

Итак, есть ли способ получить правильный SQL?

EDIT: Эти ребята тоже не удалось: Linq to SQL: как агрегировать без группы?... lame надзор дизайнеров LINQ, если на самом деле нет ответа.

РЕДАКТИРОВАТЬ 2: Я рассмотрел свое собственное решение (с предложением бессмысленной константы по условию) в анализе плана выполнения SQL Server Management Studio, и мне кажется, что он идентичен плану, создаваемому:

SELECT MIN(FavoriteNumber), MAX(FavoriteNumber)
FROM MyTable

поэтому, если кто-то не придумает более простой или равноправный ответ, я думаю, что должен отмечать его как ответ на вопрос. Мысли?

4b9b3361

Ответ 1

Как указано в вопросе, этот метод, по-видимому, фактически генерирует оптимальный код SQL, поэтому, хотя он немного похож на LINQ, он должен быть оптимальным по производительности.

from row in MyTable  
group row by true into r  
select new {  
    min = r.Min(z => z.FavoriteNumber),  
    max = r.Max(z => z.FavoriteNumber)  
} 

Ответ 2

Я мог найти только тот, который производит несколько чистый sql, который по-прежнему не эффективен по сравнению с select min (val), max (val) из таблицы:

var r =
  (from min in items.OrderBy(i => i.Value)
   from max in items.OrderByDescending(i => i.Value)
   select new {min, max}).First();

sql

SELECT TOP (1)
    [t0].[Value],
    [t1].[Value] AS [Value2]
FROM
    [TestTable] AS [t0],
    [TestTable] AS [t1]
ORDER BY
    [t0].[Value],
    [t1].[Value] DESC

все еще существует еще одна возможность использовать одно соединение для минимальных и минимальных запросов (см. Несколько активных наборов результатов (MARS))

или хранимой процедуры.

Ответ 3

Я не уверен, как перевести его на С# еще (я над этим работаю)

Это версия Haskell

minAndMax :: Ord a => [a] -> (a,a)
minAndMax [x]    = (x,x)
minAndMax (x:xs) = (min a x, max b x)
                   where (a,b) = minAndMax xs

Версия С# должна включать Aggregate как-то (я думаю).

Ответ 4

Запрос LINQ to SQL - это одно выражение. Таким образом, если вы не можете выразить свой запрос в одном выражении (или вам не нравится, когда вы это делаете), вам нужно посмотреть другие параметры.

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

(Я лично не вижу необходимости избегать двух круговых поездок здесь. Это кажется преждевременной оптимизацией, тем более, что вам, вероятно, придется прыгать через обручи, чтобы заставить ее работать. Не говоря уже о времени, которое вы потратите оправдывая это решение и объясняя решение другим разработчикам.)

Иными словами, вы уже ответили на свой вопрос. "Я не могу использовать .Min без группировки в первую очередь", а затем "это сумасшедшее предложение группы кажется глупым, а SQL-код более сложным, чем нужно", - подсказывает, что простой и понятный двух- решение "туда и обратно" - лучшее выражение вашего намерения (если вы не написали собственный SQL).

Ответ 5

Вы можете выбрать всю таблицу и выполнить свои операции min и max в памяти:

var cache = // select *

var min = cache.Min(...);
var max = cache.Max(...);

В зависимости от того, насколько велик ваш набор данных, это может быть способ не использовать вашу базу данных более одного раза.