【问题标题】:BigQuery: SPLIT() returns only one valueBigQuery:SPLIT() 仅返回一个值
【发布时间】:2015-01-19 13:00:27
【问题描述】:

我有一个页面 URL 列的组成部分由/ 分隔。我尝试在 BigQuery 中运行 SPLIT() 函数,但它只给出第一个值。我想要特定列中的所有值。

我不明白如何使用Split string into multiple columns with bigquery 中提到的Regexp_extract() 示例。

我需要类似于REGEX_SPLIT_TO_TABLE(<String>, <DELIMITER>) 的东西,它将单个字符串转换为多列。

查询:

SELECT PK, 
DATE(TIMESTAMP(CONCAT(SUBSTR(date,1,4),'-',SUBSTR(date,5,2),'-',SUBSTR(date,7,2),' 00:00:00'))) as visit_date,
hits_page_pagePath,
split(hits_page_pagePath,'/')
FROM [Intent.All2mon] limit 100

【问题讨论】:

  • 数据是什么样的?
  • 嗨 Felipe,您能帮我了解如何准备正则表达式以从“/”符号内的每个实体中提取信息吗?
  • 您无法在 BigQuery 中生成可变数量的列,只能生成固定数量的列,因此您无法完全按照自己的意愿进行操作。如果您可以设置 URL 组件数量的上限,那么您可以生成那么多列,并在特定 URL 的组件较少​​时将它们设为 NULL。

标签: google-bigquery


【解决方案1】:

这对我有用:

SELECT SPLIT(path, '/') part
FROM (SELECT "/a/b/aaaa?c" path)

Row part     
1   a    
2   b    
3   aaaa?c

不知道为什么它不适合你。您的数据是什么样的?

【讨论】:

  • SPLIT() 将列值拆分为行而不添加行号。
  • 我需要的是一种将 '/' 之间的字符串的每个实例分离到单独的列中的方法...无需为每个可能的实例运行单独的 split() 查询...
  • 我已经建立了这个查询:SELECT date, hits_time, fullVisitorId, visitNumber, hits_hitNumber, hits_page_pagePath, REGEXP_EXTRACT(hits_page_pagePath,r'/(\w*)\/') as one, REGEXP_EXTRACT(hits_page_pagePath, r'/\w*\/(\w*)') 作为两个,REGEXP_EXTRACT(hits_page_pagePath,r'/.*\/.*\/(.*)\/') 作为三个来自 [Intent.All2mon] 限制1000 但它仍然没有分离出字符串...
  • 这应该可行 - 你能分享一个示例数据集,以便我可以对你的数据运行查询吗?我无权访问 [Intent.All2mon]
  • 注意:如果您选择目标表并取消选中“展平结果”,您将得到一个包含重复部分列的单行。
【解决方案2】:

以某种方式解决它。

   SELECT
   date, 
   hits_time, 
   fullVisitorId, 
   visitNumber, 
   hits_hitNumber,
   X.page_path,
   REGEXP_EXTRACT(X.page_path,r'/(\w*)\/') as one,
   REGEXP_EXTRACT(X.page_path,r'/\w*\/(\w*)') as two,
   REGEXP_EXTRACT(X.page_path,r'/\w*\/\w*\/(\w*)') as three,
   REGEXP_EXTRACT(X.page_path,r'/\w*/\w*/\w*\/(\w*)\/.*') as four
   from
   (
   select 
   date, hits_time, fullVisitorId, visitNumber, hits_hitNumber,
   REGEXP_REPLACE (hits_page_pagePath, '-', '') as page_path
   from
   [Intent.All2mon]
   ) X 
   limit 1000

【讨论】:

    【解决方案3】:

    2018 标准 SQL 更新:

    #standardSQL
    SELECT SPLIT(path, '/')[OFFSET(0)] part1,
           SPLIT(path, '/')[OFFSET(1)] part2,
           SPLIT(path, '/')[OFFSET(2)] part3
    FROM (SELECT "/a/b/aaaa?c" path)
    

    现在我了解到您希望它们位于不同的列中。

    您提供的查询的替代方法:

    SELECT FIRST(SPLIT(path, '/')) part1,
           NTH(2, SPLIT(path, '/')) part2,
           NTH(3, SPLIT(path, '/')) part3
    FROM (SELECT "/a/b/aaaa?c" path)
    

    NTH(X, SPLIT(s)) 将提供 SPLIT 中的第 X 个值。 FIRST(s)NTH(1, s) 相同

    【讨论】:

    • 您能否检查一下 [OFFSET(2)] 在某些情况下是否不存在,因此它不会溢出?比如:IF(SPLIT(path, '/')[OFFSET(2)].doesnt_exist), Null, SPLIT(path, '/')[OFFSET(2)]?
    • 带 SAFE 的前缀。 - 或发布一个新问题 ;)
    • @FelipeHoffa,第二个查询似乎在 BigQuery 中不起作用。但是第一个很酷!
    【解决方案4】:

    在标准sql中,可以使用以下函数:

    array[OFFSET(zero_based_offset)]
    array[ORDINAL(one_based_ordinal)]
    

    所以

    SELECT SPLIT(path, '/')[OFFSET(1)] part2,
           SPLIT(path, '/')[ORDINAL(2)] part2_again,
           SPLIT(path, '/')[ORDINAL(3)] part3
    FROM (SELECT "/a/b/aaaa?c" path)
    
    part2   part2_again part3    
    a       a           b
    

    part1 在这种情况下是空字符串(在第一个斜杠之前)

    【讨论】:

      【解决方案5】:

      您也可以使用 SPLIT 函数尝试以下操作,但是您需要知道您的 url 将有多少个“/”或输入足够多的条目,以便如果您的 url 包含更多“/”,那么您仍然可以在单独的列

        SPLIT(`url`, '/')[safe_ordinal(1)] AS `Col1`, 
        SPLIT(`url`, '/')[safe_ordinal(2)] AS `Col2`,
        SPLIT(`url`, '/')[safe_ordinal(3)] AS `Col3`, 
        SPLIT(`url`, '/')[safe_ordinal(4)] AS `Col4`,
        .
        .
        SPLIT(`url`, '/')[safe_ordinal(N)] AS `ColN`
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-22
        • 1970-01-01
        • 2011-12-27
        • 2016-08-04
        • 1970-01-01
        • 2013-01-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多