Linq to SQL - Как упорядочить числа в виде строк? - PullRequest
2 голосов
/ 25 августа 2011

У меня есть столбец SQL varchar со значениями вроде 100, 2000 и S5000. Я хочу, чтобы они были упорядочены по номерам, а не по алфавиту. Если есть строковый символ, я рад, что этот символ либо игнорируется, либо появляется после числовых значений в порядке сортировки.

В T-SQL я мог бы это с:

SELECT * FROM tbl
ORDER BY
  CASE
    WHEN ISNUMERIC(fld) = 1 THEN CONVERT(INT, fld)
    ELSE 2147483647
    END ASC,
  fld ASC

Мне интересно, есть ли способ сделать это в Linq to SQL?

В противном случае, я полагаю, мои альтернативы - выполнить запрос напрямую или создать вычисляемый столбец со значениями, такими как 00000100, 00002000,000S5000 и т. Д.

Редактировать: я нашел решение, хотя я не уверен, насколько оно эффективно.

from s in q
orderby (SqlMethods.Like(s.fld, "%[^0-9]%") ? Int32.MaxValue : Convert.ToInt32(s.fld)) ascending, s.fld ascending
select s;

Ответы [ 3 ]

2 голосов
/ 09 января 2012

Я нашел решение, хотя не уверен, насколько оно эффективно.

from s in q orderby (SqlMethods.Like(s.fld, "%[^0-9]%") ? Int32.MaxValue : Convert.ToInt32(s.fld)) ascending, s.fld ascending select s; 
1 голос
/ 25 августа 2011

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

Сначала определите функцию tryParse, которую можно использовать в запросе linq-to-objects:

Func<string, int> tryParse = s =>
{
    int i;
    if (!int.TryParse(s, out i))
    {
        i = int.MaxValue;
    }
    return i;
};

Тогда фактический запрос на сортировку прост:

var query =
    from t in tbls.ToArray() // force the linq-to-sql query to execute
    orderby t.fld
    orderby tryParse(t.fld)
    select t;

Полегче, да?

0 голосов
/ 25 августа 2011

Я знаю, что вопрос был о Linq-to-SQL, но я подумал, что предоставлю ответ Entity Framework 4 для всех пользователей EF, которые наткнулись на этот вопрос, ища способ сделать это в этой среде.У меня нет опыта работы с Linq-to-SQL, так что, насколько я знаю, это действительно сработало бы там (но я сомневаюсь в этом).

Dim results = (From item in ctx.tbl
               Let sortValue = If(SqlFunctions.IsNumeric(item.fld) = 1, CInt(item.fld), 2147483647)
               Order By sortValue).ToList()

Это примерно превращается в этот запрос магазина:

SELECT [Project1].*
FROM ( SELECT 
    [Extent1].*
    CASE WHEN (1 = (ISNUMERIC([Extent1].[Value]))) THEN  CAST( [Extent1].[Value] AS int) ELSE 99999999 END AS [C2]
    FROM [dbo].[tbl] AS [Extent1]
)  AS [Project1]
ORDER BY [Project1].[C2] ASC

Это решение использует System.Data.Objects.SqlClient.SqlFunctions для непосредственного прямого вызова функции SQL ISNUMERIC в запросе.Я хочу отметить, что IsNumeric вернет 1 даже для десятичных чисел , и приведение "десятичного" varchar в int вызовет проблему.Это может быть безопаснее CDbl() вместо CInt() значения, если только вы не знаете, что ваши данные никогда не будут ничем иным, как «int» varchar.

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