Предложение SQL OrderBy для буквенно-цифровых данных в LINQ не сортируется должным образом

#c# #sql-server #linq #sorting #alphanumeric

#c# #sql-сервер #linq #сортировка #буквенно-цифровой

Вопрос:

У меня есть отчет служб SQL Server Reporting Services (SSRS), который использует order by сортировку SQL и возвращает следующее для буквенно-цифровых строковых данных:

 Value: 0.0
Value: 20.96
Value: 289.64
Value: 30.99
Value: 308.655
Value: -32296.32
Value: 34.844
Value: 38.95
Value: -697.38
Value: -703.48
  

Каждая строка имеет следующий формат:

 `Value: numeric data`
  

SQL order by , похоже, сортируется как строка, но игнорирует знак минус перед числовыми значениями.

Я использую C # с LINQ для сортировки строк, чтобы попытаться сопоставить эту сортировку:

 var _sorted = _unsortedValues.OrderBy(x => x.Description);
  

Я получаю:

 Value: -32296.32
Value: -697.38
Value: -703.48
Value: 0.0
Value: 20.96
Value: 289.64
Value: 30.99
Value: 308.655
Value: 34.844
Value: 38.95
  

LINQ по умолчанию сортирует жала со всеми значениями минус сначала по возрастанию, за которыми следуют нулевые, а затем положительные значения

Есть идеи о том, как получить желаемую сортировку для репликации сортировки SSRS?

ПРИМЕЧАНИЕ

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

 "Timestamp: data time data"
"Identifier: string data"
  

Комментарии:

1. Я только что попробовал это в Linqpad в виде списка строк и упорядочил его так, как вы ищете. Поскольку я не могу воспроизвести вашу проблему, мне нужна дополнительная информация, пожалуйста. как заполняется описание и можете ли вы показать больше кода, чтобы показать, как оно заполняется, и класс, в котором оно находится.

2. дайте нам больше кода. Ваш код должен работать на основе данных, которые вы нам предоставили

Ответ №1:

Я полагаю, что под LINQ здесь вы подразумеваете обычную ссылку на объекты, а не Entity Framework или LINQ на sql. Способ сортировки строк зависит от используемого средства сравнения, и вы можете передать в оператор любое средство сравнения, которое вам нравится OrderBy . Так, например, чтобы получить желаемую сортировку, вы можете сделать это:

 var sorted = _unsortedValues.OrderBy(x => x.Description, StringComparer.InvariantCulture).ToArray();
  

Который вернет тот же порядок, что и ваш оператор SQL.

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

 var sorted = _unsortedValues.OrderBy(x => x.Description, StringComparer.Ordinal).ToArray();
  

Вы получите порядок, как в вашем вопросе (сначала отрицательные числа).

Почему вы получаете тот порядок, который получаете, но другие люди не могут его воспроизвести? Это потому, что по умолчанию CurrentCulture используется средство сравнения строк, и текущий язык может отличаться для разных машин, поэтому люди получают разные результаты.

 var sorted = _unsortedValues.OrderBy(x => x.Description, StringComparer.CurrentCulture).ToArray(); // this is what is done by default
  

Комментарии:

1. Спасибо за решение Evk. У меня также были проблемы с корпусом, поэтому я использовал «StringComparer. InvariantCultureIgnoreCase», которое решает как мои проблемы с корпусом, так и с сортировкой.

Ответ №2:

Как вы можете видеть, ваши строки отсортированы в алфавитном порядке. Здесь нет магии. Число 289.64 идет впереди 30.99 . Если вы хотите отсортировать по числам внутри строк, вы должны извлечь эти числа. Вы можете использовать регулярное выражение, но Substring здесь должно работать simple, потому что все строки имеют одинаковый префикс перед номером:

 var startIndex = "Value: ".Length;
var _sorted = _unsortedValues
                .OrderBy(x => Double.Parse(x.Description.Substring(startIndex)));
  

ПРИМЕЧАНИЕ: подумайте о том, чтобы избавиться от Value: префикса на стороне сервера, поскольку он не предоставляет никаких реальных данных.

Комментарии:

1. Я полагаю, что лучше использовать средство сравнения по умолчанию (например, InvariantCulture).

2. @Evk я не уверен, что проблема с сортировкой операций связана только со знаком минус. Ваше решение все равно вернется 289.64 , прежде 30.99 чем игнорировать числовые значения.

3. Но OP не нуждается в числовой сортировке — ему нужна та же сортировка, что и его SQL-запрос возвращает, и это решение обеспечивает именно это.