2017-04-25 75 views
3

我有一些麻烦有效地排序表(表中包含大量的行,所以任何优化会产生很大的差异)。如何有效地对包含数字和字母的nvarchar进行排序?

我目前得到的结果是正确的(11)是下面的代码。

BEGIN TRANSACTION 

    CREATE TABLE #tPallets 
    (
     PalletNumber bigint, 
     Placement nvarchar(4) 
    ) 

    INSERT INTO #tPallets VALUES(100000, 'B') 
    INSERT INTO #tPallets VALUES(100001, 'M1') 
    INSERT INTO #tPallets VALUES(100002, 'M2') 
    INSERT INTO #tPallets VALUES(100003, 'M3') 
    INSERT INTO #tPallets VALUES(100004, 'M4') 
    INSERT INTO #tPallets VALUES(100005, 'M5') 
    INSERT INTO #tPallets VALUES(100006, 'M6') 
    INSERT INTO #tPallets VALUES(100007, 'M7') 
    INSERT INTO #tPallets VALUES(100008, 'M8') 
    INSERT INTO #tPallets VALUES(100009, 'M9') 
    INSERT INTO #tPallets VALUES(100010, 'M10') 
    INSERT INTO #tPallets VALUES(100011, 'M11') 

    SELECT 
     TOP 1 CASE 
      WHEN Placement LIKE 'M%' THEN CONVERT(int, SUBSTRING(Placement,2, len(Placement)-1)) 
      ELSE 0 
     END AS PALLET_PLACEMENT 
    FROM 
     #tPallets 
    ORDER BY 
     1 DESC 

ROLLBACK TRANSACTION 

所以我正在寻找一种方法来使选择更快,如果这可能在这种特定的情况。


我不认为这是重复的答案方式。由于在线程中没有答案会使得执行时间更快,而无需在C#中进行排序(而不是在TSql中进行排序)。我很难相信在TSql本身没有更快的方法来完成它。

+0

在Microsoft SQL 2005中可能出现[自然(人类字母数字)排序]副本(http://stackoverflow.com/questions/34509/natural-human-alpha-numeric-sort-in-microsoft-sql-2005) – Dai

+0

值的结构是否一致?总是1个字母,然后是0 - 2个数字?这些字母总是大写吗? “Placement”值是否改变? –

+0

@SolomonRutzky它总是B或M1 - M150(最差)。很抱歉,很迟才回答,没有看到评论。 – Danieboy

回答

0

与你提供什么细节,试试这种方式。

CREATE TABLE #tPallets 
    (
     PalletNumber bigint, 
     Placement nvarchar(4), 
     OrderBy as CASE 
      WHEN Placement LIKE 'M%' THEN CONVERT(int, SUBSTRING(Placement,2, len(Placement)-1)) 
      ELSE 0 END 
    ) 

    INSERT INTO #tPallets VALUES(100000, 'B') 
    INSERT INTO #tPallets VALUES(100001, 'M1') 
    INSERT INTO #tPallets VALUES(100002, 'M2') 
    INSERT INTO #tPallets VALUES(100003, 'M3') 
    INSERT INTO #tPallets VALUES(100004, 'M4') 
    INSERT INTO #tPallets VALUES(100005, 'M5') 
    INSERT INTO #tPallets VALUES(100006, 'M6') 
    INSERT INTO #tPallets VALUES(100007, 'M7') 
    INSERT INTO #tPallets VALUES(100008, 'M8') 
    INSERT INTO #tPallets VALUES(100009, 'M9') 
    INSERT INTO #tPallets VALUES(100010, 'M10') 
    INSERT INTO #tPallets VALUES(100011, 'M11') 

    select * from #tPallets 
    order by OrderBy 

或者试试这个,但不确定。

select * from #tPallets 
order by BINARY_CHECKSUM(Placement) desc 
+0

这是一样快,不适用于真正的查询。我正在寻找更快的Convert/substring/len替代品。 – Danieboy

+0

即使你使计算列“持续”? – Arvo

+0

@ Danieboy,检查我的alternate.try与其他示例数据 – KumarHarsh

0

在计算列https://docs.microsoft.com/en-us/sql/relational-databases/indexes/indexes-on-computed-columns

,或者在您的情况可能是更好的一个组合过滤指数

https://docs.microsoft.com/en-us/sql/relational-databases/indexes/create-filtered-indexes

索引摆脱那些讨厌0的。 (顺便问一句,当你的placement不是like %M时,你对顺序的期望是什么?)

+0

开始时只有一个'B',它应该被看作数字0.所以在这种情况下查询返回0。 – Danieboy

+0

当然,但它是关于选择性。如果您有效地使用了'ORDER BY 0',那么除非您指定了其他条件,否则您将无法确定'TOP 1'。你会得到*一个*行,但你不知道哪一个。 – LoztInSpace

+0

你指出我正确的方向与最后的评论。我意识到在这个情景中,MAX()比TOP 1/ORDER BY 1 DESC快得多。 – Danieboy

相关问题