Sql 聚合连续值BigQuery

Sql 聚合连续值BigQuery,sql,google-bigquery,Sql,Google Bigquery,我需要使用BigQuery聚合表中的连续值,如示例所示 段只能是“A”或“B”。值是一个字符串。 基本上,对于每个ID,我只需要考虑片段=“A”,考虑到间隙。 它应该是“按日期订购”列ASC 范例 id, segment, value, date_column 1, A, 3, daytime 1, A, 2, daytime 1, A, x, daytime 1, B, 3, daytime 1, B, 3, daytime 1, B, 3, daytime 1, A, 7, daytime

我需要使用BigQuery聚合表中的连续值,如示例所示 段只能是“A”或“B”。值是一个字符串。 基本上,对于每个ID,我只需要考虑片段=“A”,考虑到间隙。 它应该是“按日期订购”列ASC

范例

id, segment, value, date_column
1, A, 3, daytime
1, A, 2, daytime
1, A, x, daytime
1, B, 3, daytime
1, B, 3, daytime
1, B, 3, daytime
1, A, 7, daytime
1, A, 3, daytime
1, B, 3, daytime
1, A, 9, daytime
1, A, 9, daytime
2, A, 3, daytime
2, B, 3, daytime
2, A, 3, daytime
2, A, m, daytime
预期结果

id, agg_values_A_segment
1, ['32x', '73', '99']
2, ['3', '3m']
我怎样才能达到这个结果? 我正在努力解决段之间的“间隙”。

SQL表表示无序集。在类似BigQuery的并行列数据库中尤其如此。此答案的其余部分假设您有一列指定行的顺序

这是一个缺口和孤岛问题。您可以使用行数的差异来标识相邻的组。然后是聚合:

select id, array_agg(vals order by min_ordercol)
from (select id, segment, string_agg(value delimiter '' order by date_column) as vals,
             min(<ordercol>) as min_ordercol
      from (select t.*,
                   row_number() over (partition by id order by date_column) as seqnum,
                   row_number() over (partition by id, segment order by date_column) as seqnum_2,
            from t
           ) t
      group by id, segment, (seqnum - seqnum_2)
     ) x
group by id;
SQL表表示无序集。在类似BigQuery的并行列数据库中尤其如此。此答案的其余部分假设您有一列指定行的顺序

这是一个缺口和孤岛问题。您可以使用行数的差异来标识相邻的组。然后是聚合:

select id, array_agg(vals order by min_ordercol)
from (select id, segment, string_agg(value delimiter '' order by date_column) as vals,
             min(<ordercol>) as min_ordercol
      from (select t.*,
                   row_number() over (partition by id order by date_column) as seqnum,
                   row_number() over (partition by id, segment order by date_column) as seqnum_2,
            from t
           ) t
      group by id, segment, (seqnum - seqnum_2)
     ) x
group by id;

BigQuery标准SQL的以下选项

选项1-使用窗口分析功能

#standardSQL
SELECT id, ARRAY_AGG(values_in_group ORDER BY grp) agg_values_A_segment
FROM (
  SELECT id, grp, STRING_AGG(value, '' ORDER BY date_column) values_in_group
  FROM (
    SELECT id, segment, value, date_column, flag, 
      COUNTIF(flag) OVER(PARTITION BY id ORDER BY date_column) grp
    FROM (
      SELECT *, IFNULL(LAG(segment) OVER(PARTITION BY id ORDER BY date_column), segment) != segment flag
      FROM `project.dataset.table`
    )
  )
  WHERE segment = 'A'
  GROUP BY id, grp
)
GROUP BY id   
您可以使用问题中的样本数据测试、播放上述内容,如下例所示:

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 1 id, 'A' segment, '3' value, DATETIME '2019-01-07T18:46:21' date_column UNION ALL
  SELECT 1, 'A', '2', '2019-01-07T18:46:22' UNION ALL
  SELECT 1, 'A', 'x', '2019-01-07T18:46:23' UNION ALL
  SELECT 1, 'B', '3', '2019-01-07T18:46:24' UNION ALL
  SELECT 1, 'B', '3', '2019-01-07T18:46:25' UNION ALL
  SELECT 1, 'B', '3', '2019-01-07T18:46:26' UNION ALL
  SELECT 1, 'A', '7', '2019-01-07T18:46:27' UNION ALL
  SELECT 1, 'A', '3', '2019-01-07T18:46:28' UNION ALL
  SELECT 1, 'B', '3', '2019-01-07T18:46:29' UNION ALL
  SELECT 1, 'A', '9', '2019-01-07T18:46:30' UNION ALL
  SELECT 1, 'A', '9', '2019-01-07T18:46:31' UNION ALL
  SELECT 2, 'A', '3', '2019-01-07T18:46:32' UNION ALL
  SELECT 2, 'B', '3', '2019-01-07T18:46:33' UNION ALL
  SELECT 2, 'A', '3', '2019-01-07T18:46:34' UNION ALL
  SELECT 2, 'A', 'm', '2019-01-07T18:46:35' 
)
SELECT id, ARRAY_AGG(values_in_group ORDER BY grp) agg_values_A_segment
FROM (
  SELECT id, grp, STRING_AGG(value, '' ORDER BY date_column) values_in_group
  FROM (
    SELECT id, segment, value, date_column, flag, 
      COUNTIF(flag) OVER(PARTITION BY id ORDER BY date_column) grp
    FROM (
      SELECT *, IFNULL(LAG(segment) OVER(PARTITION BY id ORDER BY date_column), segment) != segment flag
      FROM `project.dataset.table`
    )
  )
  WHERE segment = 'A'
  GROUP BY id, grp
)
GROUP BY id
-- ORDER BY id   
结果

Row id  agg_values_A_segment     
1   1   32x  
        73   
        99   
2   2   3    
        3m     
选项2-上面的选项应该适用于每个id的大量行,但看起来有点重-所以第二个选项更简单,但假设您有一些字符或字符序列,您肯定不会因为组合值而产生这些字符或字符序列,例如pipechar或tab,或者在下面的示例中,我选择单词“delimiter”,假设它不会作为连接的结果出现

#standardSQL
SELECT id,
  ARRAY(SELECT part FROM UNNEST(parts) part WHERE part != '') agg_values_A_segment 
FROM (
  SELECT id, 
    SPLIT(STRING_AGG(IF(segment = 'A', value, 'delimiter'), ''), 'delimiter') parts
  FROM `project.dataset.table`
  GROUP BY id
)
您可以使用相同的示例数据测试、播放上述内容:

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 1 id, 'A' segment, '3' value, DATETIME '2019-01-07T18:46:21' date_column UNION ALL
  SELECT 1, 'A', '2', '2019-01-07T18:46:22' UNION ALL
  SELECT 1, 'A', 'x', '2019-01-07T18:46:23' UNION ALL
  SELECT 1, 'B', '3', '2019-01-07T18:46:24' UNION ALL
  SELECT 1, 'B', '3', '2019-01-07T18:46:25' UNION ALL
  SELECT 1, 'B', '3', '2019-01-07T18:46:26' UNION ALL
  SELECT 1, 'A', '7', '2019-01-07T18:46:27' UNION ALL
  SELECT 1, 'A', '3', '2019-01-07T18:46:28' UNION ALL
  SELECT 1, 'B', '3', '2019-01-07T18:46:29' UNION ALL
  SELECT 1, 'A', '9', '2019-01-07T18:46:30' UNION ALL
  SELECT 1, 'A', '9', '2019-01-07T18:46:31' UNION ALL
  SELECT 2, 'A', '3', '2019-01-07T18:46:32' UNION ALL
  SELECT 2, 'B', '3', '2019-01-07T18:46:33' UNION ALL
  SELECT 2, 'A', '3', '2019-01-07T18:46:34' UNION ALL
  SELECT 2, 'A', 'm', '2019-01-07T18:46:35' 
)
SELECT id,
  ARRAY(SELECT part FROM UNNEST(parts) part WHERE part != '') agg_values_A_segment 
FROM (
  SELECT id, 
    SPLIT(STRING_AGG(IF(segment = 'A', value, 'delimiter'), ''), 'delimiter') parts
  FROM `project.dataset.table`
  GROUP BY id
)
-- ORDER BY id   
显然,结果是一样的

Row id  agg_values_A_segment     
1   1   32x  
        73   
        99   
2   2   3    
        3m      

注意:对于每个id有太多行的情况,第二个选项可能会导致超出资源-您只需要在实际数据上尝试它

以下BigQuery标准SQL选项

选项1-使用窗口分析功能

#standardSQL
SELECT id, ARRAY_AGG(values_in_group ORDER BY grp) agg_values_A_segment
FROM (
  SELECT id, grp, STRING_AGG(value, '' ORDER BY date_column) values_in_group
  FROM (
    SELECT id, segment, value, date_column, flag, 
      COUNTIF(flag) OVER(PARTITION BY id ORDER BY date_column) grp
    FROM (
      SELECT *, IFNULL(LAG(segment) OVER(PARTITION BY id ORDER BY date_column), segment) != segment flag
      FROM `project.dataset.table`
    )
  )
  WHERE segment = 'A'
  GROUP BY id, grp
)
GROUP BY id   
您可以使用问题中的样本数据测试、播放上述内容,如下例所示:

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 1 id, 'A' segment, '3' value, DATETIME '2019-01-07T18:46:21' date_column UNION ALL
  SELECT 1, 'A', '2', '2019-01-07T18:46:22' UNION ALL
  SELECT 1, 'A', 'x', '2019-01-07T18:46:23' UNION ALL
  SELECT 1, 'B', '3', '2019-01-07T18:46:24' UNION ALL
  SELECT 1, 'B', '3', '2019-01-07T18:46:25' UNION ALL
  SELECT 1, 'B', '3', '2019-01-07T18:46:26' UNION ALL
  SELECT 1, 'A', '7', '2019-01-07T18:46:27' UNION ALL
  SELECT 1, 'A', '3', '2019-01-07T18:46:28' UNION ALL
  SELECT 1, 'B', '3', '2019-01-07T18:46:29' UNION ALL
  SELECT 1, 'A', '9', '2019-01-07T18:46:30' UNION ALL
  SELECT 1, 'A', '9', '2019-01-07T18:46:31' UNION ALL
  SELECT 2, 'A', '3', '2019-01-07T18:46:32' UNION ALL
  SELECT 2, 'B', '3', '2019-01-07T18:46:33' UNION ALL
  SELECT 2, 'A', '3', '2019-01-07T18:46:34' UNION ALL
  SELECT 2, 'A', 'm', '2019-01-07T18:46:35' 
)
SELECT id, ARRAY_AGG(values_in_group ORDER BY grp) agg_values_A_segment
FROM (
  SELECT id, grp, STRING_AGG(value, '' ORDER BY date_column) values_in_group
  FROM (
    SELECT id, segment, value, date_column, flag, 
      COUNTIF(flag) OVER(PARTITION BY id ORDER BY date_column) grp
    FROM (
      SELECT *, IFNULL(LAG(segment) OVER(PARTITION BY id ORDER BY date_column), segment) != segment flag
      FROM `project.dataset.table`
    )
  )
  WHERE segment = 'A'
  GROUP BY id, grp
)
GROUP BY id
-- ORDER BY id   
结果

Row id  agg_values_A_segment     
1   1   32x  
        73   
        99   
2   2   3    
        3m     
选项2-上面的选项应该适用于每个id的大量行,但看起来有点重-所以第二个选项更简单,但假设您有一些字符或字符序列,您肯定不会因为组合值而产生这些字符或字符序列,例如pipechar或tab,或者在下面的示例中,我选择单词“delimiter”,假设它不会作为连接的结果出现

#standardSQL
SELECT id,
  ARRAY(SELECT part FROM UNNEST(parts) part WHERE part != '') agg_values_A_segment 
FROM (
  SELECT id, 
    SPLIT(STRING_AGG(IF(segment = 'A', value, 'delimiter'), ''), 'delimiter') parts
  FROM `project.dataset.table`
  GROUP BY id
)
您可以使用相同的示例数据测试、播放上述内容:

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 1 id, 'A' segment, '3' value, DATETIME '2019-01-07T18:46:21' date_column UNION ALL
  SELECT 1, 'A', '2', '2019-01-07T18:46:22' UNION ALL
  SELECT 1, 'A', 'x', '2019-01-07T18:46:23' UNION ALL
  SELECT 1, 'B', '3', '2019-01-07T18:46:24' UNION ALL
  SELECT 1, 'B', '3', '2019-01-07T18:46:25' UNION ALL
  SELECT 1, 'B', '3', '2019-01-07T18:46:26' UNION ALL
  SELECT 1, 'A', '7', '2019-01-07T18:46:27' UNION ALL
  SELECT 1, 'A', '3', '2019-01-07T18:46:28' UNION ALL
  SELECT 1, 'B', '3', '2019-01-07T18:46:29' UNION ALL
  SELECT 1, 'A', '9', '2019-01-07T18:46:30' UNION ALL
  SELECT 1, 'A', '9', '2019-01-07T18:46:31' UNION ALL
  SELECT 2, 'A', '3', '2019-01-07T18:46:32' UNION ALL
  SELECT 2, 'B', '3', '2019-01-07T18:46:33' UNION ALL
  SELECT 2, 'A', '3', '2019-01-07T18:46:34' UNION ALL
  SELECT 2, 'A', 'm', '2019-01-07T18:46:35' 
)
SELECT id,
  ARRAY(SELECT part FROM UNNEST(parts) part WHERE part != '') agg_values_A_segment 
FROM (
  SELECT id, 
    SPLIT(STRING_AGG(IF(segment = 'A', value, 'delimiter'), ''), 'delimiter') parts
  FROM `project.dataset.table`
  GROUP BY id
)
-- ORDER BY id   
显然,结果是一样的

Row id  agg_values_A_segment     
1   1   32x  
        73   
        99   
2   2   3    
        3m      

注意:如果每个id有太多行,则第二个选项可能会导致超出资源-您只需要在实际数据上尝试它

您的问题似乎是假设对行进行排序。您需要指定此排序的列。是的,该表已按日期排序。我添加了一个“日期”栏。它应该是ORDER BY date_列,因为您的问题似乎假设对行进行排序。您需要指定此排序的列。是的,该表已按日期排序。我添加了一个“日期”栏。请按日期订购,谢谢。此查询是否假定“段A”位于第一位?我想指定要拾取或的段B@Alex . . . 否。这将根据排序列按段出现的顺序对段进行分组。一旦根据排序列对“段A”值进行分组,我需要过滤掉“段B”gaps@Alex . . . 只需将where段“段B”添加到外部查询。谢谢。此查询是否假定“段A”位于第一位?我想指定要拾取或的段B@Alex . . . 否。这将根据排序列按段出现的顺序对段进行分组。一旦根据排序列对“段A”值进行分组,我需要过滤掉“段B”gaps@Alex . . . 只需将where段“段B”添加到外部查询。太棒了!它做的工作,它是非常有效的!谢谢好极了它做的工作,它是非常有效的!谢谢