在Google Analytics BigQuery中,以下查询会尝试在sessions
和hits
级别聚合信息
SELECT
visitId,
trafficSource.source as source,
trafficSource.medium as medium,
device.browser as browser,
min(hits.hour) as firstHitHour,
boolean(count(hits.eventInfo.eventCategory = "SomeValue")) as hasSomeValue
FROM
[my-table.ga_sessions_20150216]
GROUP BY
visitId, source, medium, browser;
如果在一行会话的所有匹配中,至少有一次匹配boolean(count(hits.eventInfo.eventCategory = "SomeValue")) as hasSomeValue
等于true
,则行hits.eventInfo.eventCategory
应为SomeValue
。< / p>
预期结果如下:
sessionId source medium browser firstHitHour hasSomeValue
--------------------------------------------------------------------------------------
12318 google cpc firefox 12 true
13317 google organic safari 14 null
13551 bing organic firefox 14 true
13610 orange display chrome 14 true
14381 stackoverflow referral safari 15 false
14422 google organic chrome 15 true
但是,上面提到的这条线似乎不起作用。即使我设置了一些愚蠢的值,例如hits.eventInfo.eventCategory = "Blablablabla"
,它仍然会为某些行输出true
(显然没有命中这个哑的值)。
实际上,没有count(hits.eventInfo.eventCategory = "Blablablabla")
的指令boolean()
会返回看似随机的结果(与实际计数没有任何共同点)。
这条线应该触发正确的输出?
答案 0 :(得分:1)
您可以更轻松地使用standard SQL。要检查hits
中是否存在值,请在其上使用EXISTS
子句。例如,
SELECT
visitId,
trafficSource.source as source,
trafficSource.medium as medium,
device.browser as browser,
(SELECT MIN(hour) FROM UNNEST(hits)) as firstHitHour,
EXISTS (SELECT 1 FROM UNNEST(hits) WHERE eventInfo.eventCategory = "SomeValue") as hasSomeValue
FROM
`my-table.ga_sessions_20150216`
GROUP BY
visitId, source, medium, browser;
另见migrating from legacy to standard SQL指南。
如果您确实希望坚持使用旧版SQL,则需要将WITHIN RECORD
与hits
上的计数结合使用。
答案 1 :(得分:1)
首先,使用boolean(count(hits.eventInfo.eventCategory = "SomeValue"))
的问题是,如果hits.eventInfo.eventCategory具有任何非NULL值(&#34; SomeValue&#34;或其他不同),它将返回true
当hits.eventInfo.eventCategory的所有值都为null时,它只返回false
。但这不是一个意想不到的结果:
hits.eventInfo.eventCategory = "SomeValue"
,BQ根据预期条件为每个匹配分配true
或false
非空值,null
如果该匹配具有null
{1}}值。count
&#34; 返回函数范围内非NULL值的总数&#34;,使用count(hits.eventInfo.eventCategory = "SomeValue")
(分组) by visitId)BQ返回之前获得的true
AND false
的汇总数,如果给定的visitId的所有匹配均为null
,则仅返回0。换句话说,它会计算所有非空值,而不仅仅是那些满足条件的值,因此您的查询问题就在这里。boolean(...)
按预期工作:如果最后一个表达式不为0则返回true,如果为0,则返回false;如果为0,则返回NULL(如果它不是null,则返回NULL)。其次,正如您在上次评论中所说,您可以使用some()
代替boolean(count())
,但请注意使用它时您不会获得任何null
结果,因为您最初想要在提供的示例中。如果至少有一个hits.eventInfo.eventCategory等于&#34; SomeValue&#34;你将获得true
否则false
。如果这对您没问题,我认为这是最好的选择。
但是,如果你想在会话的所有命中都有空的hits.eventInfo.eventCategory时获得null
,你可以使用:
SELECT
visitId,
trafficSource.source as source,
trafficSource.medium as medium,
device.browser as browser,
min(hits.hour) as firstHitHour,
boolean(MAX(
CASE WHEN hits.eventInfo.eventCategory = "SomeValue" THEN 1
WHEN hits.eventInfo.eventCategory != "SomeValue" THEN 0
ELSE null END
)
) as hasSomeValue
FROM
[my-table.ga_sessions_20150216]
GROUP BY
visitId, source, medium, browser
首先,对于每个命中,我们在条件满足时分配1,如果不满足则分配0,如果值为null则分配为null。其次,通过询问max()
,如果存在至少一个&#34; SomeValue&#34;我们将获得1,如果存在非空值但是所有这些都与&不同,则为0 #34; SomeValue&#34;,如果所有匹配都具有hits.eventInfo.eventCategory
的空值,则为null。最后,我们使用boolean()
来获取true
,false
或null
,具体视具体情况而定。
答案 2 :(得分:0)
我找到了一种输出所需结果的方法,使用some()
代替boolean(count())
SELECT
visitId,
trafficSource.source as source,
trafficSource.medium as medium,
device.browser as browser,
min(hits.hour) as firstHitHour,
some(hits.eventInfo.eventCategory = "SomeValue") as hasSomeValue
FROM
[my-table.ga_sessions_20150216]
GROUP BY
visitId, source, medium, browser;
我不确定为什么boolean(count())
会触发意外结果。
答案 3 :(得分:0)
尝试以下
#standardSQL
SELECT
visitId, source, medium, browser,
MIN(hour) AS firstHitHour,
LOGICAL_OR(hasValue) AS hasValue
FROM (
SELECT
visitId,
trafficSource.source AS source,
trafficSource.medium AS medium,
device.browser AS browser,
h.hour AS hour,
EXISTS(SELECT 1 FROM UNNEST(hits) WHERE eventInfo.eventCategory = "SomeValue") AS hasValue
FROM
`my-table.ga_sessions_20161122`, UNNEST(hits) AS h
)
GROUP BY
visitId, source, medium, browser;