【问题标题】:Read flat file having array in Azure Data Factory在 Azure 数据工厂中读取具有数组的平面文件
【发布时间】:2022-01-14 07:02:50
【问题描述】:

我需要读取一个以管道分隔的文件,其中我们有一个重复 30 次的数组。我需要访问这些元素数组并更改序列并在输出文件中发送。

例如

Tanya|1|Pen|2|Book|3|Eraser
Raj|11|Eraser|22|Bottle

在上面的示例中,第一个字段是客户名称。之后,我们有一个订购的商品数组 - 订单 ID 和商品名称。

您能否建议如何单独读取这些数组元素以进一步处理这些元素?

【问题讨论】:

    标签: arrays azure-data-factory azure-data-factory-2 readfile


    【解决方案1】:

    您将在 Azure 数据工厂管道中使用复制活动,其中源为 DelimitedText 数据集,接收器为 JSON 数据集。如果源文件和目标文件位于 Azure Blob 存储中,请创建链接服务以将文件与 Azure 数据工厂连接。

    源文件数据集属性将如下所示。 您需要选择 Column Delimiter 作为管道 (|)。

    具有 JSON 类型数据集设置的接收器文件如下所示。只需提及转换后将保存文件的输出位置路径即可。

    在复制数据活动接收器选项卡中,选择文件模式作为文件数组。触发管道。

    如下所示的示例输入和输出。

    【讨论】:

    • 嗨 Utkarsh,输入和输出文件都是平面文件。输入文件将用竖线分隔,输出文件将用波浪号(~) 分隔。
    • 但是您在问题中没有提到输出文件将被波浪号分隔。
    【解决方案2】:

    如果您可以控制输出文件格式,那么您最好使用两个(或三个)分隔符,一个用于人员,另一个用于订单项目。如果你能得到第三个,那么就用它把订单项从订单行中拆分出来。

    假设数据格式:

    Person Name | 1:M [Order]
    

    每个订单都是

    order line | item name
    

    您可以简单地将整行提取到单个 nvarchar(max) 列中,然后使用 SQL 分解您需要的数据。

    以下是一个这样的例子。

    declare @tbl table (d nvarchar(max));
    insert into @tbl values('Tanya|1|Pen|2|Book|3|Eraser'),('Raj|11|Eraser|22|Bottle');
    declare @base table (id int, person varchar(100),total_orders int, raw_orders varchar(max));
    declare @output table (id int, person varchar(100),item_id int, item varchar(100));
    
    with a as
    (
    select 
        CHARINDEX('|',d) idx
        ,d
        ,ROW_NUMBER() over (order by d) as id /*Or newid()*/
    from @tbl
    ), b as
    (
    select 
        id
        ,SUBSTRING(d,0,idx) person
        ,SUBSTRING(d,idx+1,LEN(d)-idx+1) order_array
        from a
    ), c as
    (
        select id, person, order_array
        ,(select count(1) from string_split(order_array,'|')) /2 orders 
        from b
    )
    insert into @base (id,person,total_orders,raw_orders)
    select id,person,orders,order_array from c
    
    declare @total_persons int = (select count(1) from @base);
    declare @person_enu int = 1;
    
    
    while @person_enu <= @total_persons
    BEGIN
     declare @total_orders int = (select total_orders from @base where id = @person_enu);
     declare @raw_orders nvarchar(max) = (select raw_orders from @base where id = @person_enu);
     declare @order_enu int = 1;
     declare @i int = 1;
     print CONCAT('Person ', @person_enu, '. Total orders: ', @total_orders);
         while @order_enu <= @total_orders
         begin
            --declare @id int = (select value from string_split(@raw_orders,'|',1) where ordinal = @i);
            --declare @val varchar(100) = (select value from string_split(@raw_orders,'|',1) where ordinal = @i+1);
            --print concat('Will process order ',@order_enu);
            --print concat('ID:',@i, ' Value:', @i+1)
            --print concat('ID:',@id, ' Value:', @val)
    
            INSERT INTO @output (id,person,item_id,item) 
            select b.id,b.person,n.value [item_id], v.value [item] from @base b
                cross apply string_split(b.raw_orders,'|',1) n
                cross apply string_split(b.raw_orders,'|',1) v
            where b.id = @person_enu and n.ordinal = @i and v.ordinal = @i+1;
    
            set @order_enu +=1;
            set @i+=2;
         end
     set @person_enu += 1;
    END
    select * from @output;
    

    【讨论】:

      猜你喜欢
      • 2021-11-28
      • 2021-09-28
      • 1970-01-01
      • 2021-09-28
      • 2021-12-12
      • 2022-11-24
      • 1970-01-01
      • 1970-01-01
      • 2021-11-04
      相关资源
      最近更新 更多