如何解析字符串的部分并将它们插入到列中

时间:2017-03-30 18:48:55

标签: sql sql-server

我的数据库中有一个存储数据的列:

 Description - (Width 1 Height 1)

我需要解析此字符串并将Width和Height插入2个新列。

我目前有这个查询:

SELECT CASE
        WHEN Description LIKE '%Width %' THEN SUBSTRING(Description, CHARINDEX('Width ', Description) + 6, 1)
      END AS Width,
      CASE
        WHEN Description LIKE '%Height %' THEN SUBSTRING(Description, CHARINDEX('Height ', Description) + 7, 1)
      END AS Height
FROM table

这个查询效果很好,但如果我有这样的条目,它只抓取第一个数字:

Description - (Width 25 Height 10)

我知道这是因为我正在使用' 1'作为我的SUBSTRING的长度,但我不知道如何使这项工作正常。

3 个答案:

答案 0 :(得分:1)

SQL Server不会使解析字符串变得容易。

SELECT LEFT(v.wstr, CHARINDEX(' ', v.wstr + ' ') - 1) as width,
       LEFT(v.hstr, CHARINDEX(' ', v.hstr + ' ') - 1) as width,      
FROM table OUTER APPLY
     (VALUES (STUFF(Description, 1, CHARINDEX('Width ', Description + 'Width ') + 6, ''), 
              STUFF(Description, 1, CHARINDEX('Height ', Description + 'Height ') + 7, ''),
             )
     ) v(wstr, hstr);

注意:

  • 与您的版本不同,当值不存在时返回空字符串,而不是NULL(很容易将CASE添加回来)。
  • 与您的版本一样,这假设图案以空格结尾。
  • 与您的版本一样,这假定“宽度”和“高度”未出现在说明中。

答案 1 :(得分:0)

如果您正在使用SQL 2016,则可以使用STRING_SPLIT并解析各个部分。

如果没有,那就更难了:

SUBSTRING

我在这里制作了一堆不同的变量来说明LEN(@testString)是如何工作的。基本上,在宽度之后获取索引,直到你到达下一个空格 - 对高度做同样的事情,除了我们正在查看25以结束它。

这将正确返回10LTRIM(RTRIM(Width))的宽度和高度。只要您可以保证字符串所在的格式,这种方法就有效 - 如果此格式发生更改,它将无法正常工作。

理想情况下,这些值将存储在数据库的不同列中 - 然后您不必担心SQL拆分字符串。

编辑:

作为旁注,您(可能)最终希望Height和{{1}}删除最终产生的子字符串中的任何空格。

答案 2 :(得分:0)

除了大小写(高度xxxxx - 宽度xxxxx)

之外,此查询可以适用于任何长度的高度,宽度
DECLARE @Description AS TABLE (Description varchar(50))
INSERT INTO @Description
VALUES( 'Width 252 Height 1011'), ('Width 2 Height 22'),('Width 2144'), ('Height 2133')

SELECT CHARINDEX('Width', 'Width 25 Height 10')
;WITH temps AS
(
    SELECT   
        CASE 
            WHEN CHARINDEX('Height', d.Description) > 1 THEN CHARINDEX('Height', d.Description)
            ELSE 1
        END AS IndexPosition,
        d.Description
    FROM @Description d
)
SELECT 
t.Description,
CASE 
    WHEN t.IndexPosition = 1 AND t.Description LIKE '%Width%' THEN RTRIM(LTRIM(REPLACE(t.Description,'Width','' ))) 
    WHEN t.IndexPosition = 1 AND t.Description LIKE '%Height%' THEN NULL
    ELSE RTRIM(LTRIM(REPLACE(SUBSTRING(t.Description, 0, t.IndexPosition -1),'Width','' ))) 
END AS Width,
CASE 
    WHEN t.IndexPosition = 1 AND t.Description LIKE '%Height%' THEN RTRIM(LTRIM(REPLACE(t.Description,'Height','' ))) 
    WHEN t.IndexPosition = 1 AND t.Description LIKE '%Width%' THEN NULL
    ELSE RTRIM(LTRIM(REPLACE(SUBSTRING(t.Description, t.IndexPosition, LEN(t.Description)),'Height','' ))) 
END AS Height
FROM temps t