SQL,BigQuery - 用行的其他部分完成缺失值
Posted
技术标签:
【中文标题】SQL,BigQuery - 用行的其他部分完成缺失值【英文标题】:SQL, BigQuery - completing missing values with other part of rows 【发布时间】:2019-12-11 17:34:16 【问题描述】:我正在使用导出到 BigQuery 的 Firebase 数据(数据包含来自移动应用程序的事件数据)。我已经对应用程序进行了更新,并且正在报告新参数。不幸的是,并非所有用户都拥有最新版本的应用程序。这就是为什么我有带有该参数的行以及没有它的行。
在event_params
我有类似的东西:
| No | contentId | contentName |
|----|-----------|---------------------|
| 1 | abc | (parameter missing) |
| 2 | abc | Name of ABC |
| 3 | cde | Name of CDE |
| 4 | efg | Name of EFG |
| 5 | abc | (parameter missing) |
| 6 | cde | Name of CDE |
现在,当我查询该表并指定(使用 UNNEST)我需要 contentName
参数时,我没有得到缺少该参数的行。
我有疑问:
SELECT
ep.value.string_value as ContentID,
ep2.value.string_value as ContentName,
COUNT(1) as `Count`
FROM
`mydataset.mytable.events_*`,
UNNEST(event_params) as ep,
UNNEST(event_params) as ep2
WHERE
event_name="my_event_name" AND
ep.key="contentID" AND
ep2.key="contentName"
GROUP BY 1,2
我得到:
| No | contentId | contentName | Count |
|----|-----------|-------------|-------|
| 1 | abc | Name of ABC | 1 |
| 2 | cde | Name of CDE | 2 |
| 3 | efg | Name of EFG | 1 |
但是,我想得到:
| No | contentId | contentName | Count |
|----|-----------|-------------|-------|
| 1 | abc | Name of ABC | 3 |
| 2 | cde | Name of CDE | 2 |
| 3 | efg | Name of EFG | 1 |
我想以某种方式完成缺少 contentName
参数的行,使用来自具有相同 contentId
的其他行的值(我们可以假设每个 contentId 具有相同的常量 contentName)
我怎样才能实现它?我想 SELF JOIN,但 BigQuery 不建议这样做。
【问题讨论】:
我的理解是,您的真正要求是您帖子最后一段的第二段 - 您应该展示您的输入数据和所需输出的示例 - 向我们展示您的中间故障排除数据 - 对我们没有多大帮助帮助你 - 但仍然很有价值,因为它提供了一些额外的信息 - 但主要信息仍然缺失 @MikhailBerlyant 我不明白你还有什么期望。我已经发布了我的 event_params 内容、我的查询、我想要的输出以及我通过当前查询获得的输出 - 你提到的所有内容 :) 这些示例如何支持您的以下语句“我想使用来自具有相同 contentId 的其他行的值以某种方式完成缺少 contentName 参数的行”?我不明白怎么做! 表格的每一行代表来自应用程序的一个事件。每行都有 event_params 数组。其中一些行在 event_params 中包含 contentName 参数,而其中一些行包含没有 contentName 的 event_params,但所有行都包含 contentId 参数。我想计算所有行(有和没有 contentName)——我可以只查询 contentID(所有行都包含它),但我还需要 contentName 值——这就是为什么我需要从包含这两个参数的行中获取它的原因。 我对UNNEST、event_params以及分析这些数据的理解来自:medium.com/firebase-developers/… 【参考方案1】:Gordon 提供的解决方案可以稍作修改,以达到您想要的效果:
SELECT contentId.value.string_value as ContentID,
MAX(contentName.value.string_value) as ContentName,
COUNT(1) as `Count`
FROM `mydataset.mytable.events_*` e LEFT JOIN
UNNEST(e.event_params) as contentId
ON contentId.key = 'contentID' LEFT JOIN
UNNEST(e.event_params) contentName
ON contentName.key = 'contentName'
WHERE e.event_name = 'my_event_name'
GROUP BY 1;
请注意,我仅按 ContentID 进行分组,并且使用 MAX 聚合 ContentNames,忽略空值。
我已经重新创建了您的示例表,它按预期工作。
【讨论】:
【参考方案2】:您可以更新表格以填充空值,然后进行查询
[1]
UPDATE `your_project.your_dataset.your_table` t_incomplete
SET t_incomplete.contentName = t_complete.contentName
FROM `your_project.your_dataset.your_table` t_complete
WHERE t_incomplete.contentId = t_complete.contentId
AND t_complete.contentName IS NOT NULL
我不确定这将如何与嵌套表一起使用,但您始终可以
-
更新取消嵌套
使用查询 [1] 更新
更新嵌套
您可以通过这个示例 CREATE TABLE 来描绘背后的想法
CREATE TABLE `your_project.your_dataset.sample_table`
(
id INT64,
nullable STRING
);
INSERT INTO `your_project.your_dataset.sample_table`
VALUES (1, 'foo');
INSERT INTO `your_project.your_dataset.sample_table`
VALUES (1, null);
INSERT INTO `your_project.your_dataset.sample_table`
VALUES (2, 'lel');
INSERT INTO `your_project.your_dataset.sample_table`
VALUES (1, null);
INSERT INTO `your_project.your_dataset.sample_table`
VALUES (2, null);
和查询[2]
UPDATE `your_project.your_dataset.sample_table` t_incomplete
SET t_incomplete.nullable = t_complete.nullable
FROM `wave27-sellbytel-aalbesa.trial_dataset.with_and_update` t_complete
WHERE t_incomplete.id = t_complete.id
AND t_complete.nullable IS NOT NULL
这样,您实际上为单元格提供了相应的值,您可以毫无顾虑地运行您的查询。我希望这行得通!
【讨论】:
不幸的是,更新表不是一种选择【参考方案3】:您只需要OR
条件吗?
WHERE event_name = 'my_event_name' AND
ep.key = 'contentID' AND
(ep2.key = 'contentName' OR ep2.key IS NULL)
编辑:
我认为你需要LEFT JOIN
s:
SELECT contentId.value.string_value as ContentID,
contentName.value.string_value as ContentName,
COUNT(1) as `Count`
FROM `mydataset.mytable.events_*` e LEFT JOIN
UNNEST(e.event_params) as contentId
ON contentId.key = 'contentID' LEFT JOIN
UNNEST(e.event_params) contentName
ON contentName.key = 'contentName'
WHERE e.event_name = 'my_event_name'
GROUP BY 1, 2;
注意:这应该会保留您想要的计数,但可能会导致结果集中出现额外的行。
【讨论】:
不,通过您的查询,我得到的结果与我的查询相同。使用(ep2.key="contentName" OR ep2.key IS NULL)
不会改变任何东西 - 不计算没有 contentName
参数的行。
关于更新的答案 - 我得到重复的行数(使用正确的 contentName 和 contentName=null)。我希望每个 contentId 只显示一次 - 使用正确的 contentName(取自包含这两个参数的行)。以上是关于SQL,BigQuery - 用行的其他部分完成缺失值的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法使用预编译的 sql 完成工作并通过 java api (bigquery) 多次运行