0

フリー テキスト フィールドを解析して国名を検索する SQL UDF またはステートメントを作成しようとしていますが、うまくいきません。

完全なコンテキストを提供するために、トランザクションの詳細を含むトランザクション テーブル (以下の tbltransactions) を用意しました。フィールドの 1 つは、このフリー テキスト フィールドです。これには、受取人の名前、受取人の住所、受取人の国が (この順序で) 含まれていることが理想的です。しかし、フリー テキスト フィールドで予想されるように、あらゆる種類の可能な組み合わせがあります。これは、国名のスペルが間違っている、省略されている、短縮されている、または完全に欠落している可能性があることも意味します。幸いなことに、ほとんどの取引では、テキスト ブロックの最後に国が指定されています。テーブルには、ユーザーが 3 文字の国コードを入力する別のフィールドがあります (必須)。これは、フリー テキスト フィールドに入力した内容と一致する場合と一致しない場合があります。以下は、テーブル内のダミー データです。

TransID     ISOCode BeneAddress
------------------- -----------
20          IRN     aaaa bb cccc Islamic Rupublic of Iran  
19          IRN     aaaa bb cccc Iran, Islamic Republic of

ここで、すべての国とその名前の可能なバリエーションのリストを格納するルックアップ テーブル (tblCountryMappings) を作成しました (ほとんどの場合!)。

例えば。「マケドニア共和国」、「マケドニア、旧ユーゴスラビア共和国」、「マケドニア」、「マセドニア」など。

以下は、このテーブルのダミー データです。

ID  ISONumericCode  countryName                 matchIdentifier            matchIdentifierType
----------------------------------------------------------------------------------------------
209  364            Iran, Islamic Republic of   IR                         ISOAlphaCode_2
210  364            Iran, Islamic Republic of   IRN                        ISOAlphaCode_3
495  364            Iran, Islamic Republic of   Iran                       Short_Name
1163 364            Iran, Islamic Republic of   Iran, Islamic Republic of  Original_Name
1309 364            Iran, Islamic Republic of   Islamic Rupublic of Iran   Alternate_Name

ご覧のとおり、テーブル間に 1 対多のマッピングがあります。目的は、トランザクションを分析し、それが意図された国を見つけることです ( ISO コードだけでなく、にフリーテキスト フィールドに基づいて)。たとえば、トランザクション 123 では、ISO コードに「Iraq」があり、フリー テキストに「Iran」があり、フリー テキストの一致は ISO の 3 文字の「IRN」にあることがわかります。また、境界の状況 (例: 行末、引用符で囲まれている) では一致が機能することを確認する必要がありますが、テキスト ブロックの途中にある場合 (例: サウジアラビアの 2 文字のコード「SA」と一致しない) は機能しません。だれかが「サミュエル」と呼んだ)。

フリーテキストから最後の単語を抽出するためにこの基本的なスクリプトを作成しました。これを使用して tblCountryMappings の matchIdentifier を結合できますが、明らかに非常に貧弱な試みです。

select 
    beneaddress
    ,SUBSTRING(beneaddress, 
               case when CHARINDEX(' ',REVERSE(beneaddress)) = 0 then 1 
                    else LEN(beneaddress) - CHARINDEX(' ',REVERSE(LTRIM(RTRIM(beneaddress))))+2
               end
    ,LEN(beneaddress)) as Country
from
    tblTransactions

このソリューションの構築を手伝っていただければ、本当に感謝しています。初めての投稿なのでルール違反がありましたらご容赦ください。詳細についてはお気軽にお問い合わせください。できるだけ早く投稿します。

よろしくお願いします。

乾杯

4

2 に答える 2

0

あなたの質問が理解できれば。

以下は、一致ヒット数の最大数を返します。以下に示すPARSING関数が必要です。

サンプル データの作成

Declare @YouTable table (TransID int,ISOCode varchar(50),BeneAddress varchar(500))
Insert Into @YouTable values 
(20,'IRN','aaaa bb cccc Islamic Rupublic of Iran'),
(19,'IRN','aaaa bb cccc Iran, Islamic Republic of')

Declare @ISO table (ID int,ISONumericCode int,countryName varchar(50),matchIdentifier varchar(50),matchIdentifierType varchar(50))
Insert Into @ISO values
(209  ,364,'Iran, Islamic Republic of','IR',                       'ISOAlphaCode_2'),
(210  ,364,'Iran, Islamic Republic of','IRN',                      'ISOAlphaCode_3'),
(495  ,364,'Iran, Islamic Republic of','Iran',                     'Short_Name'),
(1163 ,364,'Iran, Islamic Republic of','Iran, Islamic Republic of','Original_Name'),
(1309 ,364,'Iran, Islamic Republic of','Islamic Rupublic of Iran' ,'Alternate_Name')

実際の SQL

;with cteBase as (
        Select A.*,B.*,C.*
            From  @YouTable A
            Cross Apply (Select * from [dbo].[udf-Str-Parse](A.BeneAddress,' ')  ) B
            Cross Apply (Select * from @ISO where matchIdentifier like '%'+B.RetVal+'%') C),    
      cteSumm as (
        Select TransID,ID,RowNr=Row_Number() over (Partition By TransID Order by Count(*) Desc)
        From cteBase
        Group By TransID,ID
)
Select B.*,C.*
 From  cteSumm A
 Join  @YouTable B on (A.RowNr=1 and A.TransID = B.TransID)
 Join  @ISO C      on (A.RowNr=1 and A.ID=C.ID)

戻り値

ここに画像の説明を入力

UDF

CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimiter varchar(10))
Returns Table 
As
Return (  
    Select RetSeq = Row_Number() over (Order By (Select null))
          ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
    From (Select x = Cast('<x>'+ Replace(@String,@Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A 
    Cross Apply x.nodes('x') AS B(i)
);
--Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse]('John||Cappelletti||was||here','||')
于 2016-09-29T17:47:41.383 に答える
0

個々の街路名や州名が特定の国名に似ている可能性があるという奇妙なシナリオを想像できるので、そこに完璧な解決策があるとは思えません。LIKEルックアップ テーブルをトランザクション テーブルの useステートメントに結合できると述べました。そうすれば、正規表現を使用して住所の国と一致させることができます。国名は末尾にあるか、先頭または末尾を「,」またはスペースで区切ります。クエリを多少簡素化する必要がありますが、前述のように完璧ではありません。

次の例は、クエリがどのようになるかを示しています。

DECLARE @tbltransactions TABLE
(
     TransID        INT
    ,ISOCode        NVARCHAR(3)
    ,BeneAddress    NVARCHAR(100)
)

DECLARE @tblCountryMappings TABLE
(
     ID                 INT IDENTITY
    ,CountryName        NVARCHAR(100)
    ,MatchIdentifier    NVARCHAR(100)
)

INSERT INTO @tbltransactions
(
     TransID    
    ,ISOCode    
    ,BeneAddress
)
VALUES
(1          ,'IRN'     ,'aaaa bb cccc Islamic Rupublic of Iran') ,
(2          ,'IRN'     ,'aaaa bb cccc "Iran", Islamic Republic of'),
(3          ,'IRN'     ,'aaRSAbb cccc IRN'),
(4          ,'IRN'     ,'aaaa bb cccc IR'),
(5          ,'IRN'     ,'aaaa bb cccc The Country of Fred')


INSERT INTO @tblCountryMappings
(       
     CountryName    
    ,MatchIdentifier
)
VALUES
('Iran, Islamic Republic of',   'IR'),         
('Iran, Islamic Republic of',   'IRN'),         
('Iran, Islamic Republic of',   'Iran'),
('South Africa, Republic of',   'RSA'),
('South Africa, Republic of',   'R.S.A.'),
('South Africa, Republic of',   'South Africa')


SELECT      T.TransID
            ,T.BeneAddress
            ,ISNULL(M.CountryName, '< Could not match country>') AS CountryName
            ,M.MatchIdentifier
FROM        @tbltransactions    T
LEFT OUTER JOIN @tblCountryMappings M ON 
                ( 
                        (T.BeneAddress LIKE '%[, "]' + M.MatchIdentifier + '[, "]%') -- Match any address which contains a word that start with a comma or space or quote ([, "]) and is then followed by the MatchIdentifier and then end with either a comma or space or quote.
                                OR
                        (T.BeneAddress LIKE '%[, "]' + M.MatchIdentifier ) -- Match any address which contains a word that start with a comma or space or quote ([, "]) and is then ends with the MatchIdentifier.
                                OR
                        (T.BeneAddress LIKE M.MatchIdentifier + '[, "]%') -- Match any address which contains a word that start with the MatchIdentifier and then end with either a comma or space or quote.
                                OR
                        (T.BeneAddress LIKE M.MatchIdentifier ) -- Match the address with an exact match of the MatchIdentifier
                )

上記の例では、sql は MatchIdentifier フィールドの値に基づいて生成された正規表現で BeneAddress を照合します。

tblCountryMappings の例では、MatchIdentifier フィールドにイランの次の値が含まれます。

  • IR
  • IRN
  • イラン

これにより、次の正規表現が生成されます。

  • %[, "]IR[, "]% - コンマ、スペース、または引用符 ([, "]) で始まり、その後に IR が続き、コンマまたはスペースまたはいずれかで終わる単語を含む任意の文字列に一致します。見積もり。
  • %[, "]IRN[, "]% - コンマ、スペース、または引用符 ([, "]) で始まり、その後に IRN が続き、コンマまたはスペースまたは見積もり。
  • %[, "]Iran[, "]% - コンマ、スペース、または引用符 ([, "]) で始まり、その後にイランが続き、コンマまたはスペースまたはいずれかで終わる単語を含む任意の文字列に一致します。見積もり。

国が文字列の末尾にある可能性を照合するために、末尾にORパターン マッチが定義されていない追加の条件を含めます。国名が文字列の先頭にある可能性と一致する場合と同様に、先頭にORパターン一致が定義されていない追加条件を含めます。

于 2016-09-29T17:48:43.703 に答える