2016-09-27 64 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' 

這不是一個很好的解決方案,因此它不是一個通用的。但也許這會做或至少給你一些想法。