连接字符串的数字部分

时间:2018-07-11 20:36:22

标签: sql sql-server tsql

已经有一段时间了...我想在最有效的方法上获得您的建议,该方法仅加入一个字段的数字部分,该部分可以加前缀和/或后缀最多2个字母。这是我要执行的操作的简化代码段:

[Files]
Source: "Firebird.conf"; Flags: dontcopy

[Code]

procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep = ssPostInstall then
  begin
    Log('Installing Firebird.conf');
    ExtractTemporaryFile('Firebird.conf');
    if not FileCopy(ExpandConstant('{tmp}\Firebird.conf'),
                    ExpandConstant('{app}\Firebird.conf'), False) then
    begin
      RaiseException('Could not install Firebird.conf');
    end;
  end;
end;

SELECT a, b, c FROM table 1 t1 LEFT JOIN table 2 t2 ON t1.PolicyCode = t2.sPolicyID, 可以以2个字母开头和/或结束。一些示例:t2.sPolicyIDTG73100S7286674等。我们只想加入字母之间的数字部分,即2344506R73100或示例中的7286674

有人可以建议一个简单的方法吗?

1 个答案:

答案 0 :(得分:3)

这是一种方法:

LEFT JOIN table 2 t2 ON t1.PolicyCode =

LEFT(SUBSTRING(t2.sPolicyID, PATINDEX('%[0-9]%', t2.sPolicyID), 50),
     PATINDEX('%[^0-9]%', 
     SUBSTRING(t2.sPolicyID, PATINDEX('%[0-9]%', t2.sPolicyID), 50)
     + 'a') -1)

要对此进行分解,有四个主要部分。

1 :使用PATINDEX查找第一个数字的位置:

DECLARE @spolicyID VARCHAR(20) = 'xx123123xx'

SELECT PATINDEX('%[0-9]%', @spolicyID) 

--Returns 3

2 :使用SUBSTRING()截断第一个字母之前的所有内容:

DECLARE @spolicyID VARCHAR(20) = 'xx123123xx'

SELECT SUBSTRING(@spolicyID, PATINDEX('%[0-9]%', @spolicyID), 50) 

--Returns 123123xx

如果我们对从第一部分返回的3进行硬编码,则它看起来像这样:

DECLARE @spolicyID VARCHAR(20) = 'xx123123xx'

SELECT SUBSTRING(@spolicyID, 3), 50) 

--50 is the number of characters to extract, set to something 
--higher than the max string length to be safe

当然,我们不希望对其进行硬编码,因为它可以更改,但是这使得查看不同的功能更加容易。

3 :再次使用PATINDEX查找下一个字母的位置:

DECLARE @spolicyID VARCHAR(20) = 'xx123123xx'

SELECT PATINDEX('%[^0-9]%', SUBSTRING(@spolicyID, PATINDEX('%[0-9]%', @spolicyID), 50) + 'a')

--Returns 7 since it is looking at 123123xx
--The first x is in the 7th position

请注意,我们在字符串上添加了a。这是因为,如果我们的字符串末尾没有字母,则它将引发错误,因为长度0将返回到SUBSTRING。您可以在末尾添加任何字母,也可以使用,我们只是确保至少有一个。尝试删除+ 'a'并使用类似xx123123的字符串来查看错误。

如果我们对第2步中的123123xx进行了硬编码,则它看起来像这样(再次举个简单的例子):

DECLARE @spolicyID VARCHAR(20) = 'xx123123xx'

SELECT PATINDEX('%[^0-9]%', '123123xx' + 'a')

4 :使用LEFT()返回尾随字母前的所有内容,只留下中间的数字:

DECLARE @spolicyID VARCHAR(20) = 'xx123123xx'

LEFT(SUBSTRING(@spolicyID, PATINDEX('%[0-9]%', @spolicyID), 50),PATINDEX('%[^0-9]%', SUBSTRING(@spolicyID, PATINDEX('%[0-9]%', @spolicyID), 50) + 'a') -1)

--Need to add `-1` because step 3 PATINDEX returns 7
--as the position of first trailing letter, and
--we want the 6 characters before that

再从步骤2和3进行硬编码以方便查看:

DECLARE @spolicyID VARCHAR(20) = 'xx123123xx'

LEFT('123123xx', 7-1)