SQL LINQ 中字母数字数据的 OrderBy 子句未按预期排序
SQL OrderBy clause for alphanumeric data in LINQ not sorting as expected
我有一个 SQL Server Reporting Services (SSRS) 报告,它使用 SQL order by
排序和 returns 以下字母数字字符串数据:
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"
如您所见,您的字符串已按字母顺序排序。这里没有魔法。数字 289.64
在 30.99
之前。如果你想按字符串中的数字排序,你应该提取这些数字。您可以使用正则表达式,但简单的 Substring
应该在这里工作,因为所有字符串在数字前都有相同的前缀:
var startIndex = "Value: ".Length;
var _sorted = _unsortedValues
.OrderBy(x => Double.Parse(x.Description.Substring(startIndex)));
注意:考虑去掉服务器端的 Value:
前缀,因为它不提供任何真实数据。
我想这里的 LINQ 是指常规 LINQ to objects,而不是 Entity Framework 或 LINQ to sql。字符串的排序方式取决于使用的比较器,您可以将您喜欢的任何比较器传递给 OrderBy
语句。因此,例如要获得所需的排序,您可以这样做:
var sorted = _unsortedValues.OrderBy(x => x.Description, StringComparer.InvariantCulture).ToArray();
这将 return 与您的 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
我有一个 SQL Server Reporting Services (SSRS) 报告,它使用 SQL order by
排序和 returns 以下字母数字字符串数据:
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"
如您所见,您的字符串已按字母顺序排序。这里没有魔法。数字 289.64
在 30.99
之前。如果你想按字符串中的数字排序,你应该提取这些数字。您可以使用正则表达式,但简单的 Substring
应该在这里工作,因为所有字符串在数字前都有相同的前缀:
var startIndex = "Value: ".Length;
var _sorted = _unsortedValues
.OrderBy(x => Double.Parse(x.Description.Substring(startIndex)));
注意:考虑去掉服务器端的 Value:
前缀,因为它不提供任何真实数据。
我想这里的 LINQ 是指常规 LINQ to objects,而不是 Entity Framework 或 LINQ to sql。字符串的排序方式取决于使用的比较器,您可以将您喜欢的任何比较器传递给 OrderBy
语句。因此,例如要获得所需的排序,您可以这样做:
var sorted = _unsortedValues.OrderBy(x => x.Description, StringComparer.InvariantCulture).ToArray();
这将 return 与您的 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