通过固定关键字拆分字符串

时间:2014-06-06 06:35:20

标签: sql sql-server

您好,我目前有一个表格,我想分割一列。

    ID Serial
    1  AAA"-A01-AU-234-U_xyz(CY)(REV-002)
    2  AAA"-A01-AU-234-U(CY)(REV-1)
    3  AAA"-A01-AU-234-U(CY)(REV-101)
    4  VVV"-01-AU-234-Z_ww(REV-001)
    5  VVV"-01-AU-234-Z(REV-001)_xyz(CY)
    6  V-VV"-01-AU-234-Z(REV-03)_xyz(CY)
    7  V-VV"-01-AU-234-Z-ZZZ(REV-004)_xyz(CY)

我想通过select语句将此列拆分为2个字段

第一个字段将包含满足此方案时开始和结束的文本

  1. 在第一个“ -
  2. 之后
  3. 取所有文字直到接下来的3个爆炸( - )
  4. 在最后一次宣传( - )
  5. 之后取第一个字母

    第二个字段希望将值(Int)存储在(REV)括号内。 Rev始终存储在罗盘(Rev-xxx)内,数字可以从0-999延伸并具有不同的表示形式

    输出示例

        Field 1              Field 2
        AAA"-A01-AU-234-U    2
        AAA"-A01-AU-234-U    1
        AAA"-A01-AU-234-U    101
        VVV"-01-AU-234-Z     1
        VVV"-01-AU-234-Z     1
        V-VV"-01-AU-234-Z    3
        V-VV"-01-AU-234-Z    4
    

4 个答案:

答案 0 :(得分:2)

也许有可能让它更好更快,但至少它确实有效。如果我还有一些时间,我会再次考虑这个问题来考虑更好的解决方案,但是它可以做到这一点。

create table #t 
(
    id int,
    serial nvarchar(255)
)

go

insert into #t values (1,  'AAA"-A01-AU-234-U_xyz(CY)(REV-002)')
insert into #t values (2,  'AAA"-A01-AU-234-U(CY)(REV-1)')
insert into #t values (3, 'AAA"-A01-AU-234-U(CY)(REV-101)')
insert into #t values (4, 'VVV"-01-AU-234-Z_ww(REV-001)')
insert into #t values (5,  'VVV"-01-AU-234-Z(REV-001)_xyz(CY)')
insert into #t values (6,  'VVV"-01-AU-234-Z(REV-03)_xyz(CY)')
insert into #t values (7,  'VVV"-01-AU-234-Z(REV-004)_xyz(CY)')

go

select id, serial,
left(serial,charindex('-', serial, charindex('-', serial, charindex('-', serial, charindex('"',serial) + 2) +1) + 1) + 1) as 'Field2'
,cast( replace(left(right(serial, len(serial) - charindex('REV',serial) +1 ), CHARINDEX(')',right(serial, len(serial) - charindex('REV',serial) +1 )) - 1), 'REV-', '')as int) as 'Field1' 
from #t

go

给了我:

id  serial  Field2  Field1
1   AAA"-A01-AU-234-U_xyz(CY)(REV-002)  AAA"-A01-AU-234-U   2
2   AAA"-A01-AU-234-U(CY)(REV-1)    AAA"-A01-AU-234-U   1
3   AAA"-A01-AU-234-U(CY)(REV-101)  AAA"-A01-AU-234-U   101
4   VVV"-01-AU-234-Z_ww(REV-001)    VVV"-01-AU-234-Z    1
5   VVV"-01-AU-234-Z(REV-001)_xyz(CY)   VVV"-01-AU-234-Z    1
6   VVV"-01-AU-234-Z(REV-03)_xyz(CY)    VVV"-01-AU-234-Z    3
7   VVV"-01-AU-234-Z(REV-004)_xyz(CY)   VVV"-01-AU-234-Z    4

答案 1 :(得分:1)

我已经更新了我的答案。现在这样好吗?

DECLARE @Table table(ID int, SERIAL nvarchar(100));
INSERT INTO @Table(ID, SERIAL)
    VALUES  ('1', 'AAA"-A01-AU-234-U_xyz(CY)(REV-002)'),
            ('2', 'AAA"-A01-AU-234-U(CY)(REV-1)'),
            ('3', 'AAA"-A01-AU-234-U(CY)(REV-101)'),
            ('4', 'VVV"-01-AU-234-Z_ww(REV-001)'),
            ('5', 'VVV"-01-AU-234-Z(REV-001)_xyz(CY)'),
            ('6', 'VVV"-01-AU-234-Z(REV-03)_xyz(CY)'),
            ('7', 'VVV"-01-AU-234-Z(REV-004)_xyz(CY)'),
            ('8', 'AAA"-A01-AU-234-U-1111-(REV-111)'),
            ('9', 'AAA"-A01-AU-234-U-111111-5555(CY)(REV-101)'),
            ('10', 'V-VV"-01-AU-234-Z-ZZZ(REV-004)_xyz(CY)')

SELECT 
    ID,
    SERIAL,
    LEFT(SERIAL, P5.Pos + 1) AS Field1,
    CONVERT(int, SUBSTRING(SERIAL, P6.Pos, CHARINDEX(')', RIGHT(SERIAL, LEN(SERIAL) - P6.Pos)))) AS Field2
FROM @Table
    CROSS APPLY (SELECT CHARINDEX('"-', SERIAL)) AS P1(Pos)
    CROSS APPLY (SELECT CHARINDEX('-', SERIAL, P1.Pos + 1)) AS P2(Pos)
    CROSS APPLY (SELECT CHARINDEX('-', SERIAL, P2.Pos + 1)) AS P3(Pos)
    CROSS APPLY (SELECT CHARINDEX('-', SERIAL, P3.Pos + 1)) AS P4(Pos)
    CROSS APPLY (SELECT CHARINDEX('-', SERIAL, P4.Pos + 1)) AS P5(Pos)
    CROSS APPLY (SELECT CHARINDEX('REV-', SERIAL, P5.Pos + 1) + 4) AS P6(Pos)

答案 2 :(得分:1)

试试这个解决方案。它使用charindex和子串函数的组合。

 DECLARE @TempTable table
 (
     id int,
     serial nvarchar(255)
 )

 insert into @TempTable values (1, 'AAA"-A01-AU-234-U_xyz(CY)(REV-002)')
 insert into @TempTable values (2, 'AAA"-A01-AU-234-U(CY)(REV-1)')
 insert into @TempTable values (3, 'AAA"-A01-AU-234-U(CY)(REV-101)')
 insert into @TempTable values (4, 'VVV"-01-AU-234-Z_ww(REV-001)')
 insert into @TempTable values (5, 'VVV"-01-AU-234-Z(REV-001)_xyz(CY)')
 insert into @TempTable values (6, 'VVV"-01-AU-234-Z(REV-03)_xyz(CY)')
 insert into @TempTable values (7, 'VVV"-01-AU-234-Z(REV-004)_xyz(CY)')

 select 
   id, 
   serial,
   substring(serial, 1, P4.Pos+1) as field1, 
   convert(int, substring(Serial, P6.Pos , P7.Pos - P6.Pos)) as field2
 from @TempTable
   cross apply (select (charindex('-', Serial))) as P1(Pos)
   cross apply (select (charindex('-', Serial, P1.Pos+1))) as P2(Pos)
   cross apply (select (charindex('-', Serial, P2.Pos+1))) as P3(Pos)
   cross apply (select (charindex('-', Serial, P3.Pos+1))) as P4(Pos)
   cross apply (select (charindex('REV-', Serial,P1.Pos+1)+4)) as P6(Pos)
   --+4 because 'REV-' is 4 chars long
   cross apply (select (charindex(')', Serial,P6.Pos+1))) as P7(Pos);

答案 3 :(得分:1)

我在php中使用正则表达式想出了一个解决方案。我正在尝试将其转换为mysql.Anyways支持的posix标准,同时你可以看看这个并且它工作得很完美。 / 第一个脚本选择字段1的值,即AAA" -A01-AU-234-U /

<?php


  $txt='VVV"-01-AU-234-Z(REV-001)_xyz(CY)';

  $re1='((?:[a-z][a-z0-9_]*))'; 
    $re2='.*?'; 
  $re3='(\\d+)';    
  $re4='.*?';   
  $re5='((?:[a-z][a-z0-9_]*))'; 
  $re6='.*?';   
  $re7='(\\d+)';    
  $re8='.*?';   
  $re9='([a-z])';   
echo $re1.$re2.$re3.$re4.$re5.$re6.$re7.$re8.$re9;
  if ($c=preg_match_all ("/".$re1.$re2.$re3.$re4.$re5.$re6.$re7.$re8.$re9."/is", $txt, $matches))
  {
      $var1=$matches[1][0];
      $int1=$matches[2][0];
      $var2=$matches[3][0];
      $int2=$matches[4][0];
      $w1=$matches[5][0];
      print "($var1) ($int1) ($var2) ($int2) ($w1) \n";
  }


?>

 /*The second script selects values for field 2 namely the last integer*/
<?php


  $txt='VVV"-01-AU-234-Z_ww(REV-001)';

  $re1='.*?';   
  $re2='\\d';   
  $re3='.*?';   
  $re4='\\d';   
  $re5='.*?';   
  $re6='\\d';   
  $re7='.*?';   
  $re8='\\d';   
  $re9='.*?';   
  $re10='\\d';  
  $re11='.*?';  
  $re12='\\d';  
  $re13='.*?';  
    $re14='\\d';    
  $re15='(\\d)';    

  if ($c=preg_match_all ("/".$re1.$re2.$re3.$re4.$re5.$re6.$re7.$re8.$re9.$re10.$re11.$re12.$re13.$re14.$re15."/is", $txt, $matches))
  {
      $d1=$matches[1][0];
      print "($d1) \n";
  }


?>




OUTPUT:

(VVV) (01) (AU) (234) (Z) //script 1
(1) //script 2

您可以向脚本添加数据库连接并将结果存储在新表中。您可以将每行作为脚本的输入进行迭代,并将相应的结果存储在表中。

注意:

用于选择字段1的正则表达式:

((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?([a-z])

用于选择字段2的正则表达式:

 .*?\d.*?\d.*?\d.*?\d.*?\d.*?\d.*?\d(\d)

如果有人可以将上述表达式转换为posix标准,那么用户可以编写一个简单的查询,如

select t.serial as field 1 from table t 
where t.serial regexp 'converted exp' join 
(select t1.serial as field 2 from table t1
 where t1.serial regexp 'converted exp')q 
on q.id=t.id;

我试图转换它但是匹配的约束丢失了。你应该实际改变?:到^和?到[^&gt;] 和// d到[0-9]或数字。希望它有帮助。