使用SQL PATINDEX提取字符串,不同大小的子字符串

时间:2014-09-12 15:15:50

标签: sql regex sql-server-2012 substring

我试图提取###x######x##,有时候#x#。有时在数字和x之间可能存在空格。基本上,我可能遇到像

这样的字符串
  • 720x60
  • 720x600
  • 720 x 60
  • 720_x_60
  • 的1x1

我使用PATINDEX()查找模式'%[0-9]%x%[0-9]%'的第一个匹配项。到现在为止还挺好。然后我用PATINDEX()找到之后第一次出现非数字字符串。这是我遇到麻烦的地方。我在屏幕截图中得到了结果。代码也在下面。

SELECT *
    ,CASE WHEN StartInt > 0
        THEN SUBSTRING(Placement, StartInt, SizeLength) ELSE NULL END AS PlacementSize
FROM
(SELECT Placement
    --find the first occurrence of #*x*#
    ,PATINDEX('%[0-9]%x%[0-9]%',Placement) AS StartInt

    --find the first non-digit after that
    ,PATINDEX(
        '%[^0-9]%'
        ,RIGHT(
            Placement + '_' --this underscore adds at least one non-digit to find
            ,LEN(Placement)
                -
            PATINDEX('%[0-9]%x%[0-9]%',Placement) - 5
            )
        ) + 6 AS SizeLength
FROM [Staging].[Client].[A01_FY14_Reporting_staging]
WHERE [Date] > '2014-07-01') AS a

结果:

enter image description here

1 个答案:

答案 0 :(得分:4)

如果您正在处理一对数值,但也处理脏数据,并且缺乏Regex的强大功能,那么您可以在TSQL中执行此操作。

基本上,看起来你想要在'x'处将字符串分成两半,然后减去输出,直到你只有数字值。使用一组派生表,这变得相对容易(而且难以阅读)

declare @placements table (Placement varchar(10))
insert into @placements values 
('720x60'),
('720x600'),
('720 x 60'),
('720_x_60'),
('1x1')

SELECT LEFT(LeftOfX,PATINDEX('%[^0-9]%',LeftOfX) - 1) + 'x' + RIGHT(RightOfX, LEN(RightOfX) - PATINDEX('%[0-9]%', RightOfX) + 1)
FROM (
    SELECT RIGHT(LeftOfX, LEN(LeftOfX) - PATINDEX('%[0-9]%', LeftOfX) + 1) AS LeftOfX, LEFT(RightOfX, LEN(RightOfX) - PATINDEX('%[0-9]%', REVERSE(RightOfX)) + 1) AS RightOfX
    FROM (
        SELECT LEFT(p.Placement,x) AS LeftOfX, RIGHT(p.Placement,LEN(p.Placement) - x + 1) AS RightOfX
        FROM (
            SELECT
                  p.Placement
                , CHARINDEX('x',p.Placement) AS x
            FROM @placements p
            ) p
        ) p
    ) p

这是SQLFiddle example

首先,选择展示位置,展示位置中“x”的位置以及表格中的其他列。将其他列向上传递到派生表中。

接下来,将字符串拆分为左和右。

在另外两个查询中左右处理,第一个从数字部分开始取结果右边,然后在非数字部分结束左边的结果。

编辑:修正了输出,现在都选择了这两个数字。