Tsql U-SQL在两者之间联接以创建每月结果

Tsql U-SQL在两者之间联接以创建每月结果,tsql,join,between,azure-data-lake,u-sql,Tsql,Join,Between,Azure Data Lake,U Sql,编辑: 我一直在研究所需的结果。让我更好地解释一下:我试图达到的是为每个SomeData的每个YearMonth创建一行,介于开始日期和结束日期之间 例如,一些数据88888888888888888881,带有startDate 2005-12-06 00:00:00.000和结束日期2006-03-13 00:00:000。 我希望行的格式如下: 88888888888888888881, 200512 88888888888888888881, 200601 8888888888888888

编辑: 我一直在研究所需的结果。让我更好地解释一下:我试图达到的是为每个SomeData的每个YearMonth创建一行,介于开始日期和结束日期之间

例如,一些数据88888888888888888881,带有startDate 2005-12-06 00:00:00.000和结束日期2006-03-13 00:00:000。 我希望行的格式如下:

88888888888888888881, 200512
88888888888888888881, 200601
88888888888888888881, 200602
88888888888888888881, 200603
我知道这可能会将结果分解成一个巨大的文件

以下是我的帖子:

我正在尝试用U-SQL重新编写一些东西,就像我们以前在T-SQL中所做的那样

问题是,U-SQL不允许在连接期间发生中间连接

T-SQL连接看起来像这样:

SELECT rf.SomeData AS SomeData,
       rd.YearMonth AS YearMonth,
      (rf.SomeData + '-' + rd.YearMonth.ToString()) AS MonthlyKey,
       rf.SomeKey AS SomeKey
FROM MyTable rf
    INNER JOIN dbo.DimDate rd
    ON rd.Date >= rf.StartDate
    AND rd.Date <= (CASE WHEN rf.EndDate IS NULL THEN GETDATE() ELSE rf.EndDate END)
重要的是,我们要获取开始日期和结束日期之间的所有数据,并创建一个月键,以便稍后可以将某些数据与另一个表联接

我尝试过使用交叉连接,但在运行它时,它会停留在80%,而且似乎永远不会结束。它一直在一个顶点中写入GB。此外,我不确定这是否会带来同样的结果

@EditedTableCROSS =
    SELECT rfj.SomeData AS SomeData,
           rfj.StartDate AS StartDate,
           rfj.EndDate AS EndDate,
           (rfj.SomeData + "-" + dtj.YearMonth.ToString()) AS MonthlyKey, 
           rfj.SomeKey AS SomeKey

        FROM
    (
        SELECT SomeData AS SomeData,
               StartDate AS StartDate,
               EndDate AS EndDate,
               SomeKey AS SomeKey
        FROM @TableA
        WHERE SomeData != ""
    ) AS rfj

    CROSS JOIN

    (
    SELECT DISTINCT
           dt.Date AS Date,
           dt.YearMonth AS YearMonth,
           dt.Month AS Month,
           rf.StartDate AS StartDate
    FROM @date AS dt INNER JOIN @TableA AS rf ON rf.StartDate == dt.Date
    WHERE rf.StartDate >= dt.Date AND
          dt.Date <= DateTime.Now
          ) AS dtj

    WHERE rfj.StartDate <= dtj.Date AND
          rfj.EndDate >= dtj.Date;
起始日期:

2005-12-06 00:00:00.000
2011-03-29 20:57:51.000
2007-11-01 00:00:00.000
2007-11-01 00:00:00.000
2007-11-01 00:00:00.000
2011-02-28 00:00:00.000
2011-02-28 00:00:00.000
2011-02-28 00:00:00.000
2008-01-17 00:00:00.000
DimDate包含从2000年到2018年的日期

SomeDate和SomeKey看起来像:

88888888888888888881
88888888888888888882
88888888888888888883
88888888888888888884
88888888888888888885
88888888888888888886
88888888888888888887
88888888888888888888
88888888888888888889

我用这个脚本处理我生成的一些示例数据

@dateDim =
    EXTRACT xdate DateTime,
            yearMonth string
    FROM "/input/dbo.DimDate.tsv"
    USING Extractors.Tsv();

@data =
    EXTRACT 
            someKey int,
            someData string,
            startDate DateTime,
            endDate DateTime?
    FROM "/input/dbo.MyTable.tsv"
    USING Extractors.Tsv();

/*
// Use U-SQL ISNULL conditional operator which is ?
@working =
    SELECT COUNT( * ) AS records
    FROM
    (
        SELECT *
        FROM @dateDim AS dd
             CROSS JOIN
                 @data AS d
        WHERE dd.xdate BETWEEN d.startDate AND (d.endDate == (DateTime?)null ? DateTime.Now : d.endDate)
    ) AS x;
*/

@working =
    SELECT COUNT( * ) AS records
    FROM
    (
        SELECT *
        FROM @dateDim AS dd
             CROSS JOIN
                 @data AS d
        WHERE dd.xdate >= d.startDate
          AND dd.xdate <= (d.endDate == (DateTime?)null ? DateTime.Now : d.endDate)
) AS x;

我用这个脚本处理我生成的一些示例数据

@dateDim =
    EXTRACT xdate DateTime,
            yearMonth string
    FROM "/input/dbo.DimDate.tsv"
    USING Extractors.Tsv();

@data =
    EXTRACT 
            someKey int,
            someData string,
            startDate DateTime,
            endDate DateTime?
    FROM "/input/dbo.MyTable.tsv"
    USING Extractors.Tsv();

/*
// Use U-SQL ISNULL conditional operator which is ?
@working =
    SELECT COUNT( * ) AS records
    FROM
    (
        SELECT *
        FROM @dateDim AS dd
             CROSS JOIN
                 @data AS d
        WHERE dd.xdate BETWEEN d.startDate AND (d.endDate == (DateTime?)null ? DateTime.Now : d.endDate)
    ) AS x;
*/

@working =
    SELECT COUNT( * ) AS records
    FROM
    (
        SELECT *
        FROM @dateDim AS dd
             CROSS JOIN
                 @data AS d
        WHERE dd.xdate >= d.startDate
          AND dd.xdate <= (d.endDate == (DateTime?)null ? DateTime.Now : d.endDate)
) AS x;

U-SQL不支持谓词中的BETWEEN的原因是没有适用于非equijoin的扩展联接算法。即使我们在语法上允许它,它仍然会在计划中进入交叉连接

您要做的是获得一个可以分区的联接。一种方法是在分区键上有一个相等连接,然后在该分区内有交叉连接

然而,在你的情况下,我认为你并不真的需要加入。我认为您要做的是在开始日期和结束日期之间每天生成一行

我会用一个没有刻度限制的。以下是一个例子:

@MyTable = 
  SELECT * 
  FROM (VALUES
        (81,81,(DateTime?) DateTime.Parse("2005-12-06 00:00:00.000"),(DateTime?) DateTime.Parse("2006-03-13 10:27:13.000")),
        (82,82,(DateTime?) DateTime.Parse("2011-03-29 20:57:51.000"),(DateTime?) DateTime.Parse("2016-03-02 18:48:11.000")),
        (83,83,(DateTime?) DateTime.Parse("2007-11-01 00:00:00.000"),(DateTime?) DateTime.Parse("2016-03-02 18:42:57.000")),
        (84,84,(DateTime?) DateTime.Parse("2007-11-01 00:00:00.000"),(DateTime?) null),
        (85,85,(DateTime?) DateTime.Parse("2007-11-01 00:00:00.000"),(DateTime?) DateTime.Parse("2013-09-12 09:19:05.000")),
        (86,86,(DateTime?) DateTime.Parse("2011-02-28 00:00:00.000"),(DateTime?) null),
        (87,87,(DateTime?) DateTime.Parse("2011-02-28 00:00:00.000"),(DateTime?) DateTime.Parse("2016-03-02 18:59:37.000")),
        (88,88,(DateTime?) DateTime.Parse("2011-02-28 00:00:00.000"),(DateTime?) null),
        (89,89,(DateTime?) DateTime.Parse("2008-01-17 00:00:00.000"),(DateTime?) null)
    ) AS T(SomeKey, SomeData, StartDate, EndDate);

@res = 
  SELECT SomeKey, SomeData, StartDate, EndDate, DailyDate 
  FROM @MyTable 
       CROSS APPLY EXPLODE 
         (Enumerable.Range(0, 
               1 + (EndDate == (DateTime?) null ? DateTime.Now 
                                                : EndDate.Value).Subtract(StartDate.Value).Days)
           .Select(offset => StartDate.Value.AddDays(offset))
          ) AS T(DailyDate);

OUTPUT @res
TO "/output/test.csv"
USING Outputters.Csv(outputHeader : true);

这是一个典型的例子,基于问题场景而不是要求翻译会更容易回答:。

U-SQL不支持谓词中的BETWEEN的原因是没有适用于非equijoin的扩展联接算法。即使我们在语法上允许它,它仍然会在计划中进入交叉连接

您要做的是获得一个可以分区的联接。一种方法是在分区键上有一个相等连接,然后在该分区内有交叉连接

然而,在你的情况下,我认为你并不真的需要加入。我认为您要做的是在开始日期和结束日期之间每天生成一行

我会用一个没有刻度限制的。以下是一个例子:

@MyTable = 
  SELECT * 
  FROM (VALUES
        (81,81,(DateTime?) DateTime.Parse("2005-12-06 00:00:00.000"),(DateTime?) DateTime.Parse("2006-03-13 10:27:13.000")),
        (82,82,(DateTime?) DateTime.Parse("2011-03-29 20:57:51.000"),(DateTime?) DateTime.Parse("2016-03-02 18:48:11.000")),
        (83,83,(DateTime?) DateTime.Parse("2007-11-01 00:00:00.000"),(DateTime?) DateTime.Parse("2016-03-02 18:42:57.000")),
        (84,84,(DateTime?) DateTime.Parse("2007-11-01 00:00:00.000"),(DateTime?) null),
        (85,85,(DateTime?) DateTime.Parse("2007-11-01 00:00:00.000"),(DateTime?) DateTime.Parse("2013-09-12 09:19:05.000")),
        (86,86,(DateTime?) DateTime.Parse("2011-02-28 00:00:00.000"),(DateTime?) null),
        (87,87,(DateTime?) DateTime.Parse("2011-02-28 00:00:00.000"),(DateTime?) DateTime.Parse("2016-03-02 18:59:37.000")),
        (88,88,(DateTime?) DateTime.Parse("2011-02-28 00:00:00.000"),(DateTime?) null),
        (89,89,(DateTime?) DateTime.Parse("2008-01-17 00:00:00.000"),(DateTime?) null)
    ) AS T(SomeKey, SomeData, StartDate, EndDate);

@res = 
  SELECT SomeKey, SomeData, StartDate, EndDate, DailyDate 
  FROM @MyTable 
       CROSS APPLY EXPLODE 
         (Enumerable.Range(0, 
               1 + (EndDate == (DateTime?) null ? DateTime.Now 
                                                : EndDate.Value).Subtract(StartDate.Value).Days)
           .Select(offset => StartDate.Value.AddDays(offset))
          ) AS T(DailyDate);

OUTPUT @res
TO "/output/test.csv"
USING Outputters.Csv(outputHeader : true);


这是一个典型的例子,根据问题场景提问而不是要求翻译会更容易回答:。

在TSQL中,您可以使用isnullrf.EndDate、getdateSample数据、预期结果,请?@wBob我添加了样本数据。@Paparazzi感谢您的提示。wBob的回答是否解决了您的问题?至于为什么交叉连接会出现问题:请确保可以以某种方式对连接进行分区。否则,所有数据都将通过管道传输到单个顶点,并且考虑到您的连接很可能会爆炸数据集,顶点的时间可能会不足5小时,或者通常效率非常低。在TSQL中,您可以使用isnullrf.EndDate、getdateSample data、,请给出预期结果?@wBob我添加了样本数据。@狗仔队谢谢你的提示。wBob的回答是否解决了你的问题?至于为什么交叉连接会出现问题:请确保可以以某种方式对连接进行分区。否则,所有数据都将通过管道传输到单个顶点,并且考虑到您的连接很可能会爆炸数据集,顶点可能会在5小时内用完,或者通常效率非常低。谢谢Bob,我编辑了我的问题,以便更好地解释所需的结果。你能告诉我你的查询是否也是这样吗?谢谢你,鲍勃,我做了一些调整。上面的查询输出重复项。而cdd.Day==1或cdd.Date==cff.StartDate,where子句解决了这个问题。谢谢Bob,我编辑了我的问题,以便更好地解释所需的结果。你能告诉我你的查询是否也是这样吗?谢谢你,鲍勃,我做了一些调整。上面的查询输出重复项。并且cdd.Day==1或cdd.Date==cff.StartDate到where子句修复了这个问题。看起来我需要改进我的LINQ!:哇!我印象深刻。我将对此进行调查交叉应用是一种功能强大且常常被低估的SQL功能。与C中的IEnumerables相结合,它更强大,更适合扩展环境:看起来我需要改进我的LINQ!:哇!我印象深刻。我将对此进行调查交叉应用是一种功能强大且常常被低估的SQL功能。与C中的IEnumerables相结合,它甚至更强大,更适合于scal e out环境: