【问题标题】:How to convert strings into column names in Google Bigquery?如何在 Google Bigquery 中将字符串转换为列名?
【发布时间】:2020-06-02 02:57:35
【问题描述】:

我在 Google Bigquery 中有一个大型数据集,其中包含数百万行我正在尝试清理的脏数据(应用程序跟踪)。我的一个问题是,对于应用程序中触发的不同事件,相同的数据被发送到不同的列。我的意思是,对于某些事件,该国家/地区可能被发送到自定义维度 1,但对于其他事件,该国家/地区被发送到自定义维度 147。我无法发布实际数据,但SELECT * FROM table_with_dirty_data 会产生如下内容:

date | session | eventAction | cd001 | cd002    | cd004    | cd005 
-----|---------|-------------|-------|----------|----------|-------
1    | 1       | 'event_1'   | '1'   | 'Pizza'  | null     | '21'
1    | 1       | 'event_2'   | '10'  | '25'     | 'Pizza'  | '14.56'
1    | 1       | 'event_3'   | '3.1' | null     | '15'     | 'France'
1    | 2       | 'event_1'   | '6'   | 'Burger' | null     | '21'
1    | 2       | 'event_2'   | '21'  | '25'     | 'Burger' | '12.6'

这里的最终目标是最终得到一个可以分析的干净表。像这样的:

date | session | eventAction | country  | vendor   | product  | price
-----|---------|-------------|----------|----------|----------|-------
1    | 1       | 'event_1'   | 'France' | '1'      | 'Pizza'  | '14.56'
1    | 1       | 'event_2'   | 'France' | '1'      | 'Pizza'  | '14.56'
1    | 1       | 'event_3'   | 'France' | '1'      | 'Pizza'  | '14.56'
1    | 2       | 'event_1'   | 'Spain'  | '25'     | 'Burger' | '12.6'
1    | 2       | 'event_2'   | 'Spain'  | '25'     | 'Burger' | '12.6'

我知道某些事件需要某种程度的统计插补和数据类型转换,但现在我只关心将每个变量放入自己的列中。所以我创建了一个辅助表(我们称之为matrix),如下所示:

event_name | variable_1 | variable_2 | variable_3
-----------|------------|------------|----------
'event_1'  | 'cd020'    | 'cd035'    | 'cd120'
'event_2'  | 'cd020'    | 'cd146'    | 'cd056'
'event_3'  | 'cd001'    | 'cd020'    | 'cd035'

以此类推,其中variable_#列的每个单元格中的值就是table_with_dirty_data中可以找到信息的列名。也就是说,variable_1 可以在名为 cd020 的列中找到 event_name 为“event_1”和“even_2”的事件,但在名为 cd001 的列中找到 event_name 为“event_3”的事件。所以基本上matrix 所做的是将每个变量为每个事件发送到哪个自定义维度。

现在...我在 table_with_dirty_data 上有数百个不同的事件,matrix 包含所有 200 个 GA 自定义维度,所以做类似的事情

SELECT 
  CASE 
    WHEN event_name = 'event_1' THEN cd020
    WHEN event_name = 'event_2' THEN cd020
    WHEN event_name = 'event_3' THEN cd001
  END AS variable_1
  , CASE
    WHEN event_name = 'event_1' THEN cd035
    WHEN event_name = 'event_2' THEN cd146
    WHEN event_name = 'event_3' THEN cd020
    END AS variable_2
  , CASE
    WHEN event_name = 'event_1' THEN cd120
    WHEN event_name = 'event_2' THEN cd056
    WHEN event_name = 'event_3' THEN cd035
  END AS variable_3
FROM table_with_dirty_data

会花很长时间,而且很容易出错。我想要做的是使用SELECT 语句从存储信息的table_with_dirty_data 返回列名(cd###),并使用WHILE 循环所有不同的事件。因此,例如,event_name = 'event_1' 会是这样的:

SELECT 
  CASE WHEN event_name = 'event_1' THEN (SELECT variable_1 FROM matrix WHERE event_name = 'event_1') END AS variable_1
  , CASE WHEN event_name = 'event_1' THEN (SELECT variable_2 FROM matrix WHERE event_name = 'event_1') END AS variable_2
  , CASE WHEN event_name = 'event_1' THEN (SELECT variable_3 FROM matrix WHERE event_name = 'event_1') END AS variable_3
FROM table_with_dirty_data
WHERE event_name = 'event_1'

这里的目标是,然后我可以循环使用所有 event_names 的数组(这很容易实现)。最终我需要一张桌子上的所有事件,但我可以有一张桌子来策划每个事件,只要它可以以编程方式完成(我个人不知道它在 GBQ 中是否可能......会有检查)。

问题是我使用的SELECT 语句被评估为字符串,因此CASE 子句中的查询结果是字符串文字。例如,如果我要为 event = 'event_1' 运行它,

SELECT variable_1 FROM matrix WHERE event_name = 'event_1'

评估为

'cd020'

然后导致外部查询变为

SELECT 
  CASE WHEN event_name = 'event_1' THEN 'cd020' END AS variable_1
  , CASE WHEN event_name = 'event_1' THEN 'cd035' END AS variable_2
  , CASE WHEN event_name = 'event_1' THEN 'cd120' END AS variable_3
FROM table_with_dirty_data
WHERE event_name = 'event_1'

生成这样的表格

event_name | variable_1 | variable_2 | variable_3
-----------|------------|------------|----------
'event_1'  | 'cd020'    | 'cd035'    | 'cd120'
'event_1'  | 'cd020'    | 'cd035'    | 'cd120'
'event_1'  | 'cd020'    | 'cd035'    | 'cd120'

而不是每次找到事件“event_1”时返回存储在cd020cd035cd120 列中的值。

有谁知道取消引用这些内部查询结果的方法,以便在执行外部查询时将它们转换为列名(因此“cd020”变为cd020)??

PS:如果有人知道的话,我也对完全不同的策略持开放态度。

【问题讨论】:

  • 我可以向您推荐更好的方法,但是您能否提供几行示例数据和预期输出?您想为每个事件分别创建一个表格吗?
  • @SabriKaragönen 我已经编辑了这个问题。希望现在更清楚了。真的很期待听到不同的方式。谢谢

标签: google-bigquery


【解决方案1】:

听起来EXECUTE IMMEDIATE 可能会有所帮助。我不确定我是否完全理解映射,但它应该允许您根据 matrix 表编写动态语句。

但是,根据描述不清楚生成的查询可能有多笨重,因为您提到有数百种此类事件,并且您可能会开始遇到其他问题,例如查询复杂性或长度限制。

【讨论】:

    【解决方案2】:

    我使用@shollyman 推荐的EXECUTE IMMEDIATE 子句解决了这个问题。我只为其中一个事件做了这件事,但我相信这回答了最初的问题(将其扩展到其他事件只是编写 WHILE 循环的问题)。我会一步一步来,因为我没有使用实际的代表。

    第一步,我声明了一个名为 event 的变量,其中包含查询需要查找的事件的名称。

    DECLARE event STRING DEFAULT 'event_1';
    

    然后我声明了一个变量来保存查询需要查找变量的列名。

    DECLARE variable_name STRING DEFAULT (SELECT variable_1 from matrix WHERE event_name = event);
    

    然后我像往常一样编写查询,但使用EXECUTE IMMEDIATE 子句。我使用了三个双引号,以便我可以将其分成几行以提高可读性)。

    EXECUTE IMMEDIATE CONCAT("""
      SELECT
        CASE WHEN event_name = '""", event, "' THEN ", variable_name, """ END AS variable_1 
      FROM table_with_dirty_data
      WHERE event_name = '""", event, """'
    """);
    

    如果其他人要使用它,请注意我在一些三重双引号之前或之后使用的单引号。我这样做是因为,例如,声明的变量 event,即使它是一个字符串,似乎也被连接为事件(周围没有单引号),这会中断查询执行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-06
      • 1970-01-01
      • 2019-07-20
      • 2021-02-09
      • 2021-06-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多