nvarchar(50)列

时间:2018-02-12 14:57:52

标签: sql sql-server sorting select-query

我正在尝试编写一个查询,该查询将返回按字母数字列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&amp; FFS1.1R。

此外,我尝试使用ORDER BY,但它排序为

FFS1 ... FFS10 FFS2

1 个答案:

答案 0 :(得分:0)

这适用于由点分隔的任何部件数。每个部分的分类是字母数字。

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

结果

SELECT

一些解释:

第一个CTE会将您的代码转换为XML,允许分别处理每个部分 第二个CTE返回每个部分以及一个数字 第三个CTE重新连接您的代码,但每个部分填充为10个字符的长度 最终的ORDER BYimport re fileNames = ['123456_BI12554_AA_0021.jpg', '123456_BI125546_AA_0021.jpg'] for fileName in fileNames: print(re.findall(r'(_BI\d{5,6}_)', fileName)) #_BI12554_ #_BI125546_ 中使用了这个新的每行单字符串

最后提示:

这个设计很糟糕!您不应将这些值存储在连接的字符串中...将它们存储在单独的列中,并将它们放在一起,仅用于输出/表示层。这样做可以避免这种相当丑陋的小提琴......