我每天都会从Google Analytics中获得有关某个网站的表格。在表中有167.286行。主要目标是创建仅包含所需列和行的新表(CSV)。使用旧版SQL我有这个查询:
SELECT
CONCAT(CAST(visitId AS string), CAST(fullVisitorId AS string), CAST(visitNumber AS string), CAST(hits.hitNumber AS string)) AS identifier,
hits.hitNumber as hitNumber,
hits.page.pagePath as pagePath,
hits.page.pagePathLevel1 as pagePathLevel1,
hits.page.pagePathLevel2 as pagePathLevel2,
hits.appInfo.exitScreenName as exitScreenName,
hits.eventInfo.eventCategory as eventCategory,
hits.eventInfo.eventAction as eventAction,
hits.eventInfo.eventLabel as eventLabel,
hits.customDimensions.value as value,
hits.customDimensions.index as index,
visitId,
fullVisitorId,
date,
visitNumber,
totals.hits as hits,
totals.pageviews as pageviews,
device.deviceCategory as deviceCategory,
geoNetwork.city,
channelGrouping,
trafficSource.campaign as campaign,
trafficSource.source as source,
trafficSource.medium as medium
FROM
[project:dataset.table]
WHERE NOT hits.customDimensions.value = "PrivateUser" AND NOT hits.customDimensions.value = "LoggedIn"
在我第一时间使用WHERE语句时,我丢失了不应受WHERE语句影响的行。
在此之后,我得到了总共77.250行。但每个排除的值都有23.825行。当我将WHERE语句修改为WHERE hits.customDimensions.value = "PrivateUser"
时,我得到了23.825行。 “LoggedIn”也是如此。
167.286 - 2 * 23.825 = 119.636而不是77.250。所以我输了42.386行,我不知道为什么。 有谁知道为什么会这样?我只想拥有除了值不是PrivateUser和LoggedIn的行之外的所有行。这应该超过77.250。
此问题出现在旧版和标准SQL中。这是相同的查询,但在标准SQL中:
SELECT
columns (modified like the unnesting statement)
FROM
`project.dataset.table`, UNNEST(hits) as h, UNNEST(h.customDimensions) as c
WHERE
NOT c.value = "PrivateUser" AND NOT c.value = "LoggedIn"
我再次失去42.386行并且不知道为什么:(
我认为我更接近这个问题的原因:嵌套架构。
如果我在没有WHERE语句的情况下执行标准SQL查询,则总共得到124.900行。所以这里再次缺少42.386行。 似乎这样做的原因是数据的不必要或扁平化。
也许更好的问题是“如何在不丢失数据的情况下取消或展平我的数据?”。
如果我点击“隐藏选项”按钮。选择输出表并激活“允许大结果”和“展平结果”我收到错误消息“无法平移非重复字段命中_1”f.e。
答案 0 :(得分:2)
也许更好的问题是“如何在不丢失数据的情况下取消或展平我的数据?”。
此问题与unnesting
或flattening
您的数据无关
相反,它只是WHERE子句的工作原理:
WHERE子句通过针对bool_expression计算每一行来过滤掉行,并丢弃所有不返回TRUE的行(即返回FALSE或NULL的行)。
因此,在你的情况下,那些c.value为空的行 - 它们被排除在外,因为对于这样的行,WHERE子句返回NULL
,因此被过滤掉
您可以通过以下简化示例
看到这一点#standardSQL
WITH t AS (
SELECT NULL AS value UNION ALL
SELECT 'a' UNION ALL
SELECT 'b' )
SELECT * FROM t WHERE NOT value = 'a'
结果是
value
-----
b
正如你所看到的那样,过滤掉'a'和NULL的行
因此,正如Elliott建议的那样,您应明确声明要在结果中保留NULL,如下所示(例如)
#standardSQL
WITH t AS (
SELECT NULL AS value UNION ALL
SELECT 'a' UNION ALL
SELECT 'b' )
SELECT * FROM t WHERE NOT value = 'a' OR value IS NULL
正如所料,现在的结果是:
value
-----
b
null
作为一个选项(取决于编码首选项),您可以执行以下操作
SELECT * FROM t WHERE NOT IFNULL(value, '') = 'a'
如果在您的示例中,您想要排除多个值,则每个IFNULL(value, '')
的重复次数不是您想要的,因此您可以使用以下方法
SELECT * FROM t WHERE NOT IFNULL(value, '') IN ('a', 'b', 'c')
答案 1 :(得分:1)
BigQuery的遗留SQL方言与COUNT(*)
相比可能会产生令人困惑的语义,假设您正在使用它。如果您使用standard SQL,结果可能会如预期一样。您的查询可能类似于:
#standardSQL
SELECT COUNT(*)
FROM `your-dataset.your-table`
WHERE NOT EXISTS (
SELECT 1 FROM UNNEST(customDimensions)
WHERE value IN ('PrivateUser', 'LoggedIn')
);
或者,如果您要计算其中customDimensions
不是其中一个字符串的value
元素的数量,您可以执行以下操作:
#standardSQL
SELECT
SUM((SELECT COUNT(*) FROM UNNEST(customDimensions)
WHERE value NOT IN ('PrivateUser', 'LoggedIn'))) AS value_count
FROM `your-dataset.your-table`;
您可以在migration guide中了解有关旧版和标准SQL之间差异的更多信息。