在 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 和适当的默认值可以获得类似的行为。
也就是说,您应该详细说明输入数据和预期结果,这可能会改变解决方案。即,异常数据序列是否会发生,如果发生,预期会发生什么行为(或至少为了简单起见而容忍):
- e1, e1, e2 - 上面的代码忽略了前面的 e1
- e1, e2, e2 - 上面的代码计算了 2 个值 wrt 相同的 e1
- e1, e1, e2, e2 - 上面的代码无法识别嵌套,与情况 2 相同。
- e2 - 使用 DateTime.MinValue.
以上代码可能会崩溃 (null) 或抛出结果
等在某些复杂点上,您可能不得不通过 REDUCE ALL 推迟到自定义减速器(这是最后的手段!),但这会限制可以处理的数据大小。
在我们的项目中,我们必须根据收到的输入数据定期计算聚合和进一步计算。
一个常见的需求是计算输入数据流中某些行之间的时间差。
例如,这是我的输入数据流:
时间戳事件值
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 和适当的默认值可以获得类似的行为。
也就是说,您应该详细说明输入数据和预期结果,这可能会改变解决方案。即,异常数据序列是否会发生,如果发生,预期会发生什么行为(或至少为了简单起见而容忍):
- e1, e1, e2 - 上面的代码忽略了前面的 e1
- e1, e2, e2 - 上面的代码计算了 2 个值 wrt 相同的 e1
- e1, e1, e2, e2 - 上面的代码无法识别嵌套,与情况 2 相同。
- e2 - 使用 DateTime.MinValue. 以上代码可能会崩溃 (null) 或抛出结果
等在某些复杂点上,您可能不得不通过 REDUCE ALL 推迟到自定义减速器(这是最后的手段!),但这会限制可以处理的数据大小。