首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SQL中的AlphaNumeric排序与LINQ和.NET

SQL中的AlphaNumeric排序与LINQ和.NET
EN

Stack Overflow用户
提问于 2009-11-24 19:01:00
回答 2查看 3.3K关注 0票数 5

今天我遇到了一件我从未注意到的有趣的事情。看来,SQL和LINQ对AlphaNumeric字符串的排序不同。

数据表包含行:a G_6 P_1 D J_2 T Z_9 F_0

如果在SQL中执行Order,则得到以下结果:a D F G J P T Z 0 1 2 6 9

现在考虑以下LINQ示例:

代码语言:javascript
复制
class Program
{
    static void Main(string[] args)
    {
        var list = new List<string>()
                       {
                           "A",
                           "G",
                           "6",
                           "P",
                           "1",
                           "D",
                           "J",
                           "2",
                           "T",
                           "Z",
                           "9",
                           "F",
                           "0"
                       };
        Console.WriteLine("Default Order:");
        list.ForEach(s => Console.WriteLine(s));

        Console.WriteLine();
        Console.WriteLine("Sorted Order:");
        foreach (string s in list.OrderBy(f => f))
        {
            Console.WriteLine(s);
        }                        
    }
}

输出为0.1 2.6 9 A,D,F,G,J,P,T,Z

因此,SQL将字母放在第一位,数字放在第二位,LINQ排在第一位,字母放在第二位。我将这些结果放在一个DataGrid中,并点击了头,并且肯定它也订购了ala,所以这可能是一个更深的鸿沟,就像在.NET/Windows级别。

我遇到的问题是,我的用户希望看到他们习惯于通过SQL排序所看到的排序行为。我如何让LINQ以同样的方式行事?

更新

答案被标记在下面,但是对于那些后来偶然发现这个问题的人来说,我想重述一下,因为解决这个问题需要一个综合的答案。

( 1) dcp立即到达了我的大脑没有的地方:数据源。问题在于IBM的SQL (它使用EBCDIC排序)和已知领域中使用ASCII排序的所有技术之间的区别。感谢IBM再次提醒我为什么我现在是.NET开发人员。

2)认识到这一点,Ahmad提供了一个非常优雅的解决方案,我也无法理解:定制的IComparer。我使用了他提供的代码,它按照需要对列表进行排序。

感谢这两个StackOverflow再次通过!

更新2

昨天发帖后,我完成了这个任务,并想分享最终的结果。

昨天的帖子是一个简单的单字符列表,但实际上这些字符都嵌入在较长的字符串中。为了使用较长的字符串,我将原来的字符串比较器更改为char比较器,然后遍历字符串并比较每个字符,直到找到不匹配的字符或找出要比较的字符。下面是最后两个比较类:

公共类EbcdicCharComparer : IComparer {公共int比较( char,char y) { int xNum,yNum;bool xIsNum = Int32.TryParse(x.ToString(),out xNum);bool yIsNum = Int32.TryParse(y.ToString(),out yNum);

代码语言:javascript
复制
    // compare numbers
    if (xIsNum && yIsNum)
    {
        return xNum.CompareTo(yNum);
    }

    // compare num to char
    if (xIsNum)
    {
        return 1;
    }

    // compare num to char
    if (yIsNum)
    {
        return -1;
    }

    // compare normally
    return x.CompareTo(y);

}

}

公共类EbcdicStringComparer : IComparer {公共int比较( string x,string y) { var xArr = x.ToCharArray();var yArr = y.ToCharArray();

代码语言:javascript
复制
    var iterations = xArr.Length > yArr.Length ? yArr.Length : xArr.Length;
    var charComp = new EbcdicCharComparer();
    for (int i = 0; i < iterations; i++)
    {
        var compValue = charComp.Compare(xArr[i], yArr[i]);
        if (compValue != 0)
            return compValue;
    }

    // compare as strings
    return x.CompareTo(y);
}

}

真正的数据更像是这样:

  • 024 A 17
  • 024 A 18
  • 024 A 19
  • 024 1 19
  • 024 C 19A
  • 024 3 3
  • 024 A 3B

根据需要,比较器现在按照以下顺序返回数据:

  • 024 A 3B
  • 024 A 17
  • 024 A 18
  • 024 A 19
  • 024 C 19A
  • 024 1 19
  • 024 3 3

再次感谢所有帮助我的人。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-11-24 19:45:26

您可以使用接受过载OrderBy法的IComparer。IComparer将比较项以获得所需的结果:

代码语言:javascript
复制
public class CustomComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        double xNum, yNum;
        bool xIsNum = Double.TryParse(x, out xNum);
        bool yIsNum = Double.TryParse(y, out yNum);

        // compare numbers
        if (xIsNum && yIsNum)
        {
            return xNum.CompareTo(yNum);
        }

        // compare num to string
        if (xIsNum)
        {
            return 1;
        }

        // compare num to string
        if (yIsNum)
        {
            return -1;
        }

        // compare as strings
        return x.CompareTo(y);
    }
}

用法:

代码语言:javascript
复制
list.OrderBy(i => i, new CustomComparer())

实现可以对特定的示例数据使用Int32.TryParse,但是我使用了Double,以防列表中有"3.0“之类的内容。当然,你需要知道你的数据。如果值太大,则需要使用适当的TryParse方法。

票数 2
EN

Stack Overflow用户

发布于 2009-11-24 19:12:53

在我尝试过的数据库(Oracle和Server 2008)上,它使用ASCII排序(字母之前的数字与LINQ查询相同)进行排序。你在使用其他数据库吗?

Server查询:

代码语言:javascript
复制
SELECT 'A' col1 
UNION ALL
SELECT 'B' col1 
UNION ALL
SELECT '0' col1 
ORDER BY 1

行返回为0,A,B

Oracle查询:

代码语言:javascript
复制
SELECT 'A' col1 FROM dual
UNION ALL
SELECT 'B' col1 FROM dual
UNION ALL
SELECT '0' col1 FROM dual
ORDER BY 1

行返回为0,A,B

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1792196

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档