使用 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
我仍然想出如何在两个单独的列中显示以下内容:
- 没有子位置详细信息的位置代码,例如GLBOX ,或者只是
如果没有子位置,则为原始位置代码,例如GLFLR.
- 同时提供数字和非数字子位置详细信息,例如为了
GLBOX 有一列显示 1, 2, 3,A, B, C, D, E, F.
编辑:如果我能够完成此操作,数据应如下所示:
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
我需要编写 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
我仍然想出如何在两个单独的列中显示以下内容:
- 没有子位置详细信息的位置代码,例如GLBOX ,或者只是 如果没有子位置,则为原始位置代码,例如GLFLR.
- 同时提供数字和非数字子位置详细信息,例如为了 GLBOX 有一列显示 1, 2, 3,A, B, C, D, E, F.
编辑:如果我能够完成此操作,数据应如下所示:
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
. 之前不必要的 - 修复了一个语法错误(可能是一个额外
end
的拼写错误)。 - 使用
right()
,只是因为它看起来更简单。
substring()
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