簡體   English   中英

nvarchar(50) 列上的字母數字排序

[英]Alphanumeric sort on nvarchar(50) column

我正在嘗試編寫一個查詢,該查詢將返回按字母數字列 Code 排序的數據。

以下是我的查詢:

  SELECT * 
  FROM <<TableName>>
    CROSS APPLY (SELECT PATINDEX('[A-Z, a-z][0-9]%', [Code]),
          CHARINDEX('', [Code]) ) ca(PatPos, SpacePos)
    CROSS APPLY (SELECT CONVERT(INTEGER, CASE WHEN ca.PatPos = 1 THEN 
          SUBSTRING([Code], 2,ISNULL(NULLIF(ca.SpacePos,0)-2, 8000)) ELSE NULL END),
   CASE WHEN ca.PatPos = 1 THEN LEFT([Code], 
          ISNULL(NULLIF(ca.SpacePos,0)-0,1)) ELSE [Code] END) ca2(OrderBy2, OrderBy1)
   WHERE [TypeID] = '1'

輸出:

FFS1
FFS2
...
FFS12
FFS1.1
FFS1.2
...
FFS1.1E
FFS1.1R
...
FFS12.1
FFS12.2
FFS.12.1E
FFS12.1R
FFS12.2E
FFS12.2R

期望的輸出:

FFS1
FFS1.1
FFS1.1E
FFS1.1R
....
FFS12
FFS12.1
FFS12.1E
FFS12.1R

我錯過或忽略了什么?

編輯:

讓我試着更好地詳細說明表格內容。 有 FFS1 - FFS12 的記錄。 這些被分成 X 個子項,即 FFS1.1 - FFS1.X 到 FFS12.1 - FFS12.X。 E 和 R 不是拼寫錯誤,每個子記錄都有兩個與之相關的代碼:FFS1.1E 和 FFS1.1R。

另外我嘗試使用 ORDER BY 但它排序為

FFS1 ... FFS10 FFS2

這適用於由點分隔的任何數量的部分。 對每個部分分別按字母數字排序。

DECLARE @YourValues TABLE(ID INT IDENTITY, SomeVal VARCHAR(100));
INSERT INTO @YourValues VALUES
 ('FFS1')
,('FFS2')
,('FFS12')
,('FFS1.1')
,('FFS1.2')
,('FFS1.1E')
,('FFS1.1R')
,('FFS12.1')
,('FFS12.2')
,('FFS.12.1E')
,('FFS12.1R')
,('FFS12.2E')
,('FFS12.2R');

--查詢

WITH Splittable AS
(
    SELECT ID
          ,SomeVal
          ,CAST(N'<x>' + REPLACE(SomeVal,'.','</x><x>') + N'</x>' AS XML) AS Casted
    FROM @YourValues 
)
,Parted AS
(
    SELECT Splittable.*
          ,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS PartNmbr
          ,A.part.value(N'text()[1]','nvarchar(max)') AS Part
    FROM Splittable
    CROSS APPLY Splittable.Casted.nodes(N'/x') AS A(part)
)
,AddSortCrit AS
(
    SELECT ID 
          ,SomeVal
          ,(SELECT LEFT(x.Part + REPLICATE(' ',10),10) AS [*]
            FROM Parted AS x
            WHERE x.ID=Parted.ID
            ORDER BY PartNmbr
            FOR XML PATH('')
           ) AS SortColumn
    FROM Parted
    GROUP BY ID,SomeVal
)
SELECT ID
      ,SomeVal
FROM AddSortCrit 
ORDER BY SortColumn;

結果

ID  SomeVal
10  FFS.12.1E
1   FFS1
4   FFS1.1
6   FFS1.1E
7   FFS1.1R
5   FFS1.2
3   FFS12
8   FFS12.1
11  FFS12.1R
9   FFS12.2
12  FFS12.2E
13  FFS12.2R
2   FFS2

一些解釋:

第一個 CTE 會將您的代碼轉換為 XML,這樣可以分別處理每個部分。
第二個 CTE 將每個部分與一個數字一起返回。
第三個 CTE 重新連接您的代碼,但每個部分都填充到 10 個字符的長度。
最后的SELECTORDER BY使用這個新的每行單字符串

最后提示:

這個設計不好! 您不應該將這些值存儲在串聯字符串中...將它們存儲在單獨的列中,並將它們放在一起僅用於輸出/表示層。 這樣做可以避免這種相當丑陋的小提琴......

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM