>我在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
中的列名。也就是说,对于具有"event_1"和"even_2"的事件event_name
,可以在名为cd020
的列中找到variable_1
,但在名为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_name
的数组(这很容易实现(。最终,我需要将所有事件放在一个表中,但我可以有一个表来策划每个事件,只要它可以以编程方式完成(我个人不知道这在 GBQ 中是否可行......将不得不检查这一点(。
问题是我正在使用的SELECT
语句被计算为字符串,因此CASE
子句内查询的结果是字符串文字。例如,如果我为事件 = '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'
而不是返回存储在列中的值cd020
,每次找到事件 'event_1' 时cd035
或cd120
。
有谁知道一种方法来取消引用这些内部查询的结果,以便在执行外部查询时将它们转换为列名(因此"cd020"变为cd020
(??
PS:如果有人知道的话,我也愿意接受完全不同的策略。
听起来像是立即执行可能会有所帮助的情况。我不确定我是否完全理解映射,但它应该允许您根据matrix
表编写动态语句。
但是,根据描述,不清楚生成的查询可能有多笨拙,因为您提到有数百个此类事件,并且您可能会开始遇到其他问题,例如查询复杂性或长度限制。
我按照@shollyman的建议使用EXECUTE IMMEDIATE
子句解决了这个问题。我只为其中一个事件做了这件事,但我相信这回答了最初的问题(将其扩展到其他事件只是编写一个WHILE
循环的问题(。我将逐步进行,因为我没有使用实际的 repex。
第一步,我声明了一个名为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
,即使它是一个字符串,似乎被连接为event
(周围没有单引号(,这会破坏查询执行。