使用 SQL 解析不一致的数据

Parsing inconsistent data with SQL

我需要编写 SQL 来提取重复位置代码并分离出子位置详细信息。但是,我正在使用的数据不遵循既定模式。

这是位置代码的示例(真实的 table 有 5,000 多个位置):

JR-DY-TIN DY-RHOLD DY-PREQ-TIN GLVCSH GLFLR GLBOX1 GLBOX2 GLBOX3 GLBOXA GLBOXB GLBOXC GLBOXD GL GL0001 GL0002 GL0003 GL0014 …

当它是数字时,我能够为子位置详细信息创建一个新列,但到目前为止我只有这些。

select 
  LocationCode,
  REVERSE(LEFT(REVERSE(LocationCode),PATINDEX('%[A-Za-z]%',  
  REVERSE(LocationCode))-1)) AS PaddedNumbers
from LocationTable 


Results...

LocationCode     PaddedNumbers     
------------     -------------     
JR-DY-TIN                          
DY-RHOLD                           
DY-PREQ-TIN                        
GLVCSH                             
GLFLR                              
GLBOX1           1                 
GLBOX2           2  
GLBOX3           3  
GLBOXA      
GLBOXB      
GLBOXC      
GLBOXD      
GL      
GL0001           0001   
GL0002           0002   
GL0003           0003   
GL0014           0014   

我仍然想出如何在两个单独的列中显示以下内容:

编辑:如果我能够完成此操作,数据应如下所示:

LocationCode     MainLoc        SubLoc
------------     ---------      ------
JR-DY-TIN        JR-DY-TIN                         
DY-RHOLD         DY-RHOLD                  
DY-PREQ-TIN      DY-PREQ-TIN                  
GLVCSH           GLVCSH                  
GLFLR            GLFLR                 
GLBOX1           GLBOX          1               
GLBOX2           GLBOX          2
GLBOX3           GLBOX          3
GLBOXA           GLBOX          A
GLBOXB           GLBOX          B
GLBOXC           GLBOX          C
GLBOXD           GLBOX          D
GL               GL
GL0001           GL             0001    
GL0002           GL             0002    
GL0003           GL             0003    
GL0014           GL             0014    

感谢任何帮助。

环境:SQL服务器 2008 R2。

您似乎想使用类似 parseInt 的功能,SQL Server 2008 中没有。您可以尝试使用 cast,但这不适用于您的数据类型 - varchar

我建议使用 case 语句来解析您需要的复杂逻辑。即:

select 
  LocationCode,
  case when left(LocationCode,5) like 'GLBOX%' then substring(LocationCode,5,2) 
       when left(LocationCode,3) like 'GL0%' then substring(LocationCode,3,4)
       else 'null' end as ParsedLocationCode end
from LocationTable 

约翰的回答似乎基本正确。我会写成:

select LocationCode,
       (case when LocationCode like 'GLBOX%' then right(LocationCode, 1) 
             when LocationCode like 'GL%' then right(LocationCode, 4)
        end) as ParsedLocationCode
from LocationTable 

这改变了:

  • 删除 like.
  • 之前不必要的 substring()
  • 修复了一个语法错误(可能是一个额外 end 的拼写错误)。
  • 使用right(),只是因为它看起来更简单。
DECLARE @LocationRef TABLE (Location NVARCHAR(20), Ref INT)

INSERT INTO @LocationRef VALUES
     ('JR-DY-TIN',0)
    ,('DY-RHOLD',0)
    ,('DY-PREQ-TIN',0)
    ,('GLVCSH',0)
    ,('GLFLR',0)
    ,('GLBOX1',6)
    ,('GLBOX2',6)
    ,('GLBOX3',6)
    ,('GLBOXA',6)
    ,('GLBOXB',6)
    ,('GLBOXC',6)
    ,('GLBOXD',6)
    ,('GL',0)
    ,('GL0001',3)
    ,('GL0002',3)
    ,('GL0003',3)
    ,('GL0014',3)

SELECT   Location AS LocationCode
    ,LEFT(Location,CASE Ref WHEN 0 THEN LEN(Location) ELSE Ref - 1  END)
    ,RIGHT(Location,CASE Ref WHEN 0 THEN 0 ELSE LEN(Location) - Ref + 1 END)
FROM @LocationRef