代码之家  ›  专栏  ›  技术社区  ›  Gino_JrDataScientist

在Microsoft SQL Server上使用正则表达式模式提取最多三个不同长度的字符串

  •  3
  • Gino_JrDataScientist  · 技术社区  · 7 年前

    目标

    在Microsoft SQL Server表中,我有一个字符串列。该列最多包含三个指定疾病的所谓ICD代码。 目标是从每行中提取最多三个长度不同的字符串,并将其存储在3列中。如果发现的代码少于三个,则可以使用NAs。例如,如果只有一个有效代码,则第一列应填充代码,其余两列应包含NAs。

    背景

    ICD代码的长度是可变的,并且是结构化的

    [Letter][2 to 4 numbers][optional letter]
    

    每行最多可包含3个ICD代码。这些代码没有被任何东西隔开,而是在彼此之后编写的。通常中间也有垃圾在中间。

    我(在stackoverflow朋友的帮助下)编写了一个正则表达式,当在R中使用str\u match\u all函数时,它成功地提取了这三个代码。正则表达式是

    (?i)(?=([A-Z]\\d{2,4}(?:[A-Z](?!\\d{2,4}))?))
    

    问题是,我不知道如何在SQL Server中做到这一点。

    1. (可选)如何将提取的字符串“管道化”为三列?

    例子

    我拥有的数据的一个最小示例可以在这里找到 http://sqlfiddle.com/#!6/a65f1

    CREATE TABLE table1 (diagnosis varchar(100), diagnosis_1 varchar(10), diagnosis_2 varchar(10), diagnosis_3 varchar(10));
    INSERT INTO table1 (diagnosis)
    VALUES
    ("T038MFRACTURE"),
    ("M719BOCHCM531"),
    ("F900CF334M75");
    

    预期结果

    diagnosis, diagnosis_1,diagnosis_2,diagnosis_3
    T038MFRACTURE,T038M,NULL,NULL
    M719BOCHCM531,M719B,M531,NULL
    F900CF334M75,F900C,F334,M75
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Gottfried Lesigang    7 年前

    像这样的?

    CREATE TABLE table1 (diagnosis varchar(100), diagnosis_1 varchar(10), diagnosis_2 varchar(10), diagnosis_3 varchar(10));
    INSERT INTO table1 (diagnosis)
    VALUES
    ('T038MFRACTURE'),
    ('M719BOCHCM531'),
    ('F900CF334M75');
    

    WITH PosOfNonNumer AS
    (
        SELECT diagnosis AS Original
              ,diagnosis
              ,1 AS PartIndex
              ,PATINDEX('%[A-Z][0-9]%',diagnosis) AS PosFound
              ,SUBSTRING(diagnosis,1,5) AS PartFound
              ,SUBSTRING(diagnosis,PATINDEX('%[A-Z][0-9]%',diagnosis)+2,1000) AS RestString
        FROM table1
    
        UNION ALL
    
        SELECT p.Original
              ,p.RestString
              ,p.PartIndex+1
              ,PATINDEX('%[A-Z][0-9]%',p.RestString) AS PosFound
              ,SUBSTRING(p.RestString,PATINDEX('%[A-Z][0-9]%',p.RestString),5) AS PartFound
              ,SUBSTRING(p.RestString,PATINDEX('%[A-Z][0-9]%', p.RestString)+2,1000) AS RestString
        FROM PosOfNonNumer AS p
        WHERE PATINDEX('%[A-Z][0-9]%',p.RestString)>0
    )
    

    --主查询使用条件聚合来透视结果

    SELECT Original
          ,MAX(CASE WHEN PartIndex=1 THEN PartFound END) AS diag1 
          ,MAX(CASE WHEN PartIndex=2 THEN PartFound END) AS diag2 
          ,MAX(CASE WHEN PartIndex=3 THEN PartFound END) AS diag3 
          ,MAX(CASE WHEN PartIndex=4 THEN PartFound END) AS diag4 
    FROM PosOfNonNumer
    GROUP BY Original
    GO
    
    --clean-up
    --DROP TABLE table1;
    

    Original        diag1   diag2   diag3   diag4
    F900CF334M75    F900C   F334M   M75     NULL
    M719BOCHCM531   M719B   M531    NULL    NULL
    T038MFRACTURE   T038M   NULL    NULL    NULL
    

    最后你必须删掉一些角色。。。希望你能自己解决。。。