2017-04-25 79 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

相關問題