2017-09-12 86 views
3

我试图从位于英镑(#)符号后面以及之后的任何空格之前的SQL Server 2012中的字符串获取数字。例如,商店号码。比方说,我们有以下几点:SQL - 在英镑(#)符号后从字符串获取数字

Big Box Store #450 
Big Box Store #768 
Little Shop #2 
Widgets Warehouse #678 
Little Shop #5 
Widgets Warehouse #559 
Corner Boutiques #32 *CLOSED 
Corner Boutiques #67 *CLOSED 
Corner Boutiques #12 
Buy More #1047 SUPERSTORE 
1 Stop Shop #3 
1 Stop Shop #17 
You 2 Me #16 

我将返回以下:450,768,2,678,5,559,32,67,12,1047,3,17,16

正如你所看到的,并非所有的字符串在最后都有数字。他们中的一些甚至在商店的名字中有一个数字字符。我认为解决这个问题的最好方法就是提取英镑符号后面的数字。

有没有办法做到这一点?我已经看了下面的文章:

Query to get only numbers from a string

https://www.sqlservercentral.com/Forums/Topic456023-338-1.aspx

好像PATINDEX可能是很好用,但我不能确定我已经试过迄今没有返回预期结果。

非常感谢!

回答

1

另一个类似的方法...使用来自Tyron的测试数据。即使数字之后没有空格,这也是有效的。

DECLARE @t TABLE(
    MyString NVARCHAR(1000) 
); 

INSERT INTO @t VALUES 
('Big Box Store #450') 
,('Big Box Store #768') 
,('Little Shop #2') 
,('Widgets Warehouse #678') 
,('Little Shop #5') 
,('Widgets Warehouse #559') 
,('Corner Boutiques #32*CLOSED') --notice no space here 
,('Corner Boutiques #67 *CLOSED') 
,('Corner Boutiques #12') 
,('Buy More #1047 SUPERSTORE') 
,('1 Stop Shop #3') 
,('1 Stop Shop #17') 
,('You 2 Me #16'); 

select 
    SUBSTRING(MyString,CHARINDEX('#',MyString,0) + 1,case when PATINDEX('%[^0-9]%',RIGHT(MyString,LEN(MyString) - CHARINDEX('#',MyString,0))) = 0 then 99 else PATINDEX('%[^0-9]%',RIGHT(MyString,LEN(MyString) - CHARINDEX('#',MyString,0))) - 1 end) 
    --char version... 
    ,SUBSTRING(MyString,CHARINDEX('#',MyString,0) + 1,case when PATINDEX('%[^0-9]%',substring(MyString,CHARINDEX('#',MyString,0) + 1,LEN(MyString) - CHARINDEX('#',MyString,0) + 1)) = 0 then 99 else PATINDEX('%[^0-9]%',substring(MyString,CHARINDEX('#',MyString,0) + 1,LEN(MyString) - CHARINDEX('#',MyString,0) + 1)) - 1 end) 

from 
    @t 
+0

这看起来不错,我测试过,它在数据集上工作,但我的数据类型是char(65)。您的解决方案似乎只适用于varchars和nvarchars。我做错了什么,或者有其他方法吗?我甚至抛出了一些“CONVERT”函数来将它们转换为varchar(65),但那不起作用。谢谢! – jderekc

+0

@jderekc我添加了一个'CHAR'版本。 RIGHT()函数只接受'NVARCHAR'和'VARCHAR'。我用'SUBSTRING'取代了这个 – scsimon

+0

这很完美!每天学些新东西。非常感谢您的帮助,@ scsimon。 – jderekc

1

不是很漂亮,但似乎fullfill您的要求。 ;-)

DECLARE @t TABLE(
    MyString NVARCHAR(1000) 
); 

INSERT INTO @t VALUES 
('Big Box Store #450') 
,('Big Box Store #768') 
,('Little Shop #2') 
,('Widgets Warehouse #678') 
,('Little Shop #5') 
,('Widgets Warehouse #559') 
,('Corner Boutiques #32 *CLOSED') 
,('Corner Boutiques #67 *CLOSED') 
,('Corner Boutiques #12') 
,('Buy More #1047 SUPERSTORE') 
,('1 Stop Shop #3') 
,('1 Stop Shop #17') 
,('You 2 Me #16'); 

SELECT MyString 
     ,SUBSTRING(MyString 
       ,CHARINDEX('#', MyString) + 1 
       ,CASE(CHARINDEX(' ', SUBSTRING(MyString 
               ,CHARINDEX('#', MyString) + 1 
               ,LEN(MyString) - CHARINDEX('#', MyString) 
               ) 
           ) 
        ) 
        WHEN 0 THEN LEN(MyString) - CHARINDEX('#', MyString) 
        ELSE CHARINDEX(' ', SUBSTRING(MyString 
               ,CHARINDEX('#', MyString) + 1 
               ,LEN(MyString) - CHARINDEX('#', MyString) 
               ) 
           ) - 1 
        END 
       ) AS MyNumber 
    FROM @t 
+0

这工作虽然我发现有时商店将不包含数字的上市交易或者不会有间门店数量以及由scsimon预言“* CLOSED”标签的空间。但是我的数据类型是一个char(65),它适用于你的解决方案,但由于某种原因,不适用于scsimon。 谢谢! – jderekc

1

请试试这个,使用pathindex

DECLARE @TABLE AS TABLE(
name_col varchar(250) 
) 

INSERT INTO @TABLE 
SELECT 
'Big Box Store #450' UNION ALL 
SELECT'Big Box Store #768'UNION ALL 
SELECT'Little Shop #2'UNION ALL 
SELECT'Widgets Warehouse #678'UNION ALL 
SELECT'Little Shop #5'UNION ALL 
SELECT'Widgets Warehouse #559'UNION ALL 
SELECT'Corner Boutiques #32 *CLOSED'UNION ALL 
SELECT'Corner Boutiques #67 *CLOSED'UNION ALL 
SELECT'Corner Boutiques #12'UNION ALL 
SELECT'Buy More #1047 SUPERSTORE'UNION ALL 
SELECT'1 Stop Shop #3 132132'UNION ALL 
SELECT'1 Stop Shop #17'UNION ALL 
SELECT'You 2 Me #16' 

SELECT 
LEFT(SUBSTRING(
    SUBSTRING(name_col,CHARINDEX('#',name_col) + 1,LEN(name_col)), 
    PATINDEX('%[0-9.-]%',SUBSTRING(name_col,CHARINDEX('#',name_col) + 1,LEN(name_col))), 8000), 
    PATINDEX('%[^0-9.-]%', SUBSTRING(SUBSTRING(name_col,CHARINDEX('#',name_col) + 1,LEN(name_col)), 
    PATINDEX('%[0-9.-]%', SUBSTRING(name_col,CHARINDEX('#',name_col) + 1,LEN(name_col))), 8000) + 'X') -1) 

FROM @TABLE 

你的怀疑是正确的,使用PATINDEX是解决方案,请检查该链接以获得更多信息。