2016-09-27 37 views
3

我有CSV文件的内容如下删除从CSV文件的单个列分隔符,而无需打开文件

下面是CSV文件的内容:

Date_Added|this_flag|Name|DOB|SSN|ID 

2015年5月1日| Y | 静乐县| heimerscmidt | 19901002 | 123456789 | 3

May 1st, 2015|N|Jingleheimerscmidt|19901002|123456789|3 
May 5th, 2015|Y|Jon|19901001||1 
May 1st, 2015|N|Jon|19901002||1 
May 1st, 2015|Y|Jacob|19901001|234567890|2 
May 5th, 2015|N|Jingleheimerscmidt|19901001|123456789|3 
May 1st, 2015|Y|Jingleheimerscmidt|19901001|123456789|3 

正如你可以在粗体和斜体内容看,有从管道运营商除了内容的管道运营商separted columns.I希望从文本中删除管道运算符而不打开csv文件。有没有办法通过编写代码或任何其他方法来解决此问题

+0

没有打开文件?你的意思是不用在文本编辑器中打开手动执行它?该文件必须打开才能阅读其内容。您可以将它作为单个VARCHAR值引入,并根据您自己的规则剪切字符串....例如将每列分割为多行并确定何时存在太多行,然后连接回行并转回表格格式 – Matt

+1

如果您可以控制csv文件的生成,您可以添加文本限定符,例如引号,以便文本中的管道不会与摄取应用程序(或您自己的数据清理代码)与分隔符相混淆。 – Jayvee

+0

无论如何,您必须打开文件进行更改 - 无论是通过代码还是手动。 – Missy

回答

0

好吧我知道你标记了oracle,所以也许你自己或另一个Oracle guru可以从sql-server迁移此解决方案。我知道oracle有能力进行这些操作。

通常我会说你想要一个快速/奇特的方式来分割一个字符串,但在这种情况下,你需要维护分隔符之间的字符串序号位置。所以我想到了一种可以做到这一点的方法。

1)首先将CSV导入临时表中作为全部1列。现在如果您的CRLF也在名称列中找到,那么这将成为问题....但我们会认为这不是因为您没有指定它。

2)在该表上构建一个row_number用作假主键,并确定何时存在的分隔符多于应该存在的分隔符。

3)使用递归cte将字符串溢出到行中,并在以后要连接的原始字符串中保留子字符串的序号位置。

4)确定由MergePositions改变OrdinalPostion并产生DENSE_RANK()的基础上它什么行组

5)条件聚合使用OrdinalGroup作为列号码,然后使用级联方法把所有OrdginalGroup结合3排。

DECLARE @CSV as TABLE (LumpedColumns NVARCHAR(MAX)) 
INSERT INTO @CSV VALUES 
('May 1st, 2015|Y|Jingle|he|imerscmidt|19901002|123456789|3') 
,('May 1st, 2015|N|Jingleheimerscmidt|19901002|123456789|3') 
,('May 5th, 2015|Y|Jon|19901001||1') 
,('May 1st, 2015|N|Jon|19901002||1') 
,('May 1st, 2015|Y|Jacob|19901001|234567890|2') 
,('May 5th, 2015|N|Jingleheimerscmidt|19901001|123456789|3') 
,('May 1st, 2015|Y|Jingleheimerscmidt|19901001|123456789|3') 

;WITH cteFakePrimaryKey AS (
    SELECT 
     LumpedColumns 
     ,CASE WHEN LEN(LumpedColumns) - LEN(REPLACE(LumpedColumns,'|','')) > 5 THEN 
      LEN(LumpedColumns) - LEN(REPLACE(LumpedColumns,'|','')) - 5 ELSE 0 END as MergeXPositions 
     ,ROW_NUMBER() OVER (ORDER BY (SELECT 0)) as PK 
    FROM 
     @CSV 
) 


, cteRecursive AS (
    SELECT 
     PK 
     ,LumpedColumns 
     ,MergeXPositions 
     ,LEFT(LumpedColumns,CHARINDEX('|',LumpedColumns)-1) as ColValue 
     ,RIGHT(LumpedColumns,LEN(LumpedColumns) - CHARINDEX('|',LumpedColumns)) as Remaining 
     ,1 As OrdinalPosition 
    FROM 
     cteFakePrimaryKey 

    UNION ALL 

    SELECT 
     PK 
     ,LumpedColumns 
     ,MergeXPositions 
     ,LEFT(Remaining,CHARINDEX('|',Remaining)-1) 
     ,RIGHT(Remaining,LEN(Remaining) - CHARINDEX('|',Remaining)) 
     ,OrdinalPosition + 1 
    FROM 
     cteRecursive 
    WHERE 
     Remaining IS NOT NULL AND CHARINDEX('|',Remaining) > 0 

    UNION ALL 

    SELECT 
     PK 
     ,LumpedColumns 
     ,MergeXPositions 
     ,Remaining 
     ,NULL 
     ,OrdinalPosition + 1 
    FROM 
     cteRecursive 
    WHERE Remaining IS NOT NULL AND CHARINDEX('|',Remaining) = 0 
) 

, cteOrdinalGroup AS (
    SELECT 
     PK 
     ,LumpedColumns 
     ,ColValue 
     ,OrdinalPosition 
     ,DENSE_RANK() OVER (PARTITION BY PK ORDER BY 
      CASE 
      WHEN OrdinalPosition < 3 THEN OrdinalPosition 
      WHEN OrdinalPosition > (3 + MergeXPositions) THEN OrdinalPosition 
      ELSE 3 END) as OrdinalGRoup 

    FROM 
     cteRecursive 
) 

SELECT 
    PK 
    ,LumpedColumns 
    ,MAX(CASE WHEN OrdinalGRoup = 1 THEN ColValue END) as Date_Added 
    ,MAX(CASE WHEN OrdinalGRoup = 2 THEN ColValue END) as this_flag 
    ,STUFF(
     (SELECT '|' + ColValue 
     FROM 
      cteOrdinalGroup g2 
     WHERE 
      g1.PK = g2.PK 
      AND g2.OrdinalGroup = 3 
     ORDER BY 
      g2.OrdinalPosition 
     FOR XML PATH('')) 
     ,1,1,'') as name 
    ,MAX(CASE WHEN OrdinalGRoup = 4 THEN ColValue END) as DOB 
    ,MAX(CASE WHEN OrdinalGRoup = 5 THEN ColValue END) as SSN 
    ,MAX(CASE WHEN OrdinalGRoup = 6 THEN ColValue END) as ID 
FROM 
    cteOrdinalGroup g1 
GROUP BY 
    PK 
    ,LumpedColumns 
ORDER BY 
    PK 
0

如果这是你需要处理的只是一种情况下,你不希望修改该文件,你需要做的是,在Informatica的,你可以为这个Source QualifierInput Type会话属性从File更改为Command和使用sed来做替换,如:

cat $$FileName | sed -e 's/Jingle|heimerscmidt/Jingleheimerscmidt/g' 

这不是一个很好的解决方案,因此它不是一个通用的。但也许这会做或至少给你一些想法。