从csv文件的单个列中删除分隔符而不打开文件

时间:2016-09-27 20:01:44

标签: sql oracle csv informatica-powercenter

我有以下csv文件的内容

以下是CSV文件的内容:

Date_Added|this_flag|Name|DOB|SSN|ID

2015年5月1日| Y | Jingle | heimerscmidt | 19901002 | 123456789 | 3

May 1st, 2015|N|Jingleheimerscmidt|19901002|123456789|3
May 5th, 2015|Y|Jon|19901001|012345678|1
May 1st, 2015|N|Jon|19901002|012345678|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之外,内容中还有一个管道操作符。我想从文本中删除该管道操作符而不打开csv文件。有没有办法通过编写代码或任何其他方法来解决这个问题

2 个答案:

答案 0 :(得分:0)

好吧,我知道你标记了oracle,所以也许你自己或其他Oracle专家可以从sql-server迁移这个解决方案。我知道oracle能够完成这些操作。

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

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

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|012345678|1')
,('May 1st, 2015|N|Jon|19901002|012345678|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

答案 1 :(得分:0)

如果这只是您需要处理的一个案例而您不想修改文件而您需要在Informatica中执行此操作,则可以更改此Input Type的{​​{1}}会话属性Source QualifierFile并使用sed进行替换,例如:

Command

这不是一个非常好的解决方案,因此它不是一般的解决方案。但也许这会或者至少会给你一些想法。