在 Azure Data Lake Analytics U-SQL 作业中计算时差

Calculate Time Differences in Azure Data Lake Analytics U-SQL Job

在我们的项目中,我们必须根据收到的输入数据定期计算聚合和进一步计算。

一个常见的需求是计算输入数据流中某些行之间的时间差。

例如,这是我的输入数据流:

时间戳事件值
2017-05-21 11:33 e1 17
2017-05-21 11:37 e2 18
2017-05-21 11:38 e3 18
2017-05-21 11:39 e1 19
2017-05-21 11:42 e2 19

我现在想计算 e2 事件和最后接收到的 e1 事件之间的所有时间跨度(按时间戳排序)。

我希望结果是: 3分钟) 4(分钟)

类似的要求是计算相同类型事件之间的时间跨度(即 e1 事件之间的所有差异),我希望得到这样的结果: 6(分钟)

我目前的尝试:

使用 LAG 函数结合 WHEN 子句可以很容易地实现这种分析,但不幸的是,U-SQL 中缺少 WHEN 子句。 如果是 T-SQL 也可以在语句的 SELECT-Clause 中使用 Sub-Selects 来解决这个问题,但不幸的是这在 U-SQL 中也是不可能的.

您对如何解决此问题有任何建议或示例脚本吗? 非常感谢您的帮助!

在U-SQL中,可以使用c#方法进行简单的日期运算。如果您的数据像您描述的那样简单,您可以只对 e1 和 e2 事件进行排名,然后加入它们,如下所示:

@data =
    EXTRACT Timestamp DateTime,
            Event string,
            Value int
    FROM "/input/input58.csv"
    USING Extractors.Csv();

//@data = SELECT *
//     FROM (
//        VALUES
//        ( "2017-05-21 11:33", "e1", 17 ),
//        ( "2017-05-21 11:37", "e2", 18 ),
//        ( "2017-05-21 11:38", "e3", 18 ),
//        ( "2017-05-21 11:39", "e1", 19 ),
//        ( "2017-05-21 11:42", "e2", 19 )
//     ) AS T(Timestamp, Event, Value);


@e1 =
    SELECT ROW_NUMBER() OVER(ORDER BY Timestamp) AS rn,
           *
    FROM @data
    WHERE Event == "e1";

@e2 =
    SELECT ROW_NUMBER() OVER(ORDER BY Timestamp) AS rn,
           *
    FROM @data
    WHERE Event == "e2";

@working =
    SELECT
        (e2.Timestamp - e1.Timestamp).TotalSeconds AS diff_sec,
        (e2.Timestamp - e1.Timestamp).ToString() AS diff_hhmmss,
        e1.Timestamp AS ts1,
        e2.Timestamp AS ts2
    FROM @e1 AS e1
            INNER JOIN @e2 AS e2 ON e1.rn == e2.rn;


OUTPUT @working TO "/output/output.csv"
USING Outputters.Csv(quoting:false);

我的结果,示例数据显示 4 分钟和 3 分钟:

这对你有用吗?如果不是,请提供更真实的数据样本。

@data =
    SELECT
        LAST_VALUE(Event == "e1" ? Timestamp : (DateTime?)null) OVER (ORDER BY Timestamp) AS E1Time
        // MAX(Event == "e1" ? Timestamp : DateTime.MinValue) OVER (ORDER BY Timestamp) AS E1Time
        , Timestamp AS E2Time
    FROM @events
    HAVING Event == "e2"
    ;

因为 aggregates/WFs ignore null(至少他们应该,LAST_VALUE 的 U-SQL 文档没有说,所以需要确认)。这允许模拟条件行为,例如 WHEN。使用 MAX/MIN 和适当的默认值可以获得类似的行为。

也就是说,您应该详细说明输入数据和预期结果,这可能会改变解决方案。即,异常数据序列是否会发生,如果发生,预期会发生什么行为(或至少为了简单起见而容忍):

  1. e1, e1, e2 - 上面的代码忽略了前面的 e1
  2. e1, e2, e2 - 上面的代码计算了 2 个值 wrt 相同的 e1
  3. e1, e1, e2, e2 - 上面的代码无法识别嵌套,与情况 2 相同。
  4. e2 - 使用 DateTime.MinValue.
  5. 以上代码可能会崩溃 (null) 或抛出结果

等在某些复杂点上,您可能不得不通过 REDUCE ALL 推迟到自定义减速器(这是最后的手段!),但这会限制可以处理的数据大小。