BigQuery:根据匹配和产品范围维度过滤掉匹配

Posted

技术标签:

【中文标题】BigQuery:根据匹配和产品范围维度过滤掉匹配【英文标题】:BigQuery: filter out hits based on hit and product scope dimensions 【发布时间】:2018-12-23 15:13:04 【问题描述】:

在 BigQuery 中,有如下所述的基于 Google Analytics 的查询,并且可以正常工作。

#standard sql   
SELECT
      Date,
      SUM(totals.visits) AS Sessions,
      SUM(totals.transactions) AS Transactions
    FROM
      `[projectID].[DatasetID].ga_sessions_*`
    WHERE
      _TABLE_SUFFIX BETWEEN '20181217'
      AND '20181217'
      AND totals.visits > 0
    GROUP BY
      Date

在此查询中,我需要排除所有匹配在匹配中...

..GA 自定义维度 #23(命中范围)包含值“编辑器” 或 ..GA 自定义维度 #6(产品范围)匹配正则表达式值 '^63.....$' 或 ..GA hits.page.pagePath 匹配正则表达式值'gebak|cake'

注意:不是打算在会话级别(如this screenshot)但在命中级别应用上述 3 个条件,因为我想重现数字来自另一个 GA 视图,而不是从中将数据加载到 BigQuery 的视图。在这个其他 GA 视图中,上述 3 个条件被设置为视图过滤器。

到目前为止,“最佳”查询是下面的查询(基于下面 Martin Weitzmann 的帖子)。但是,此查询中没有过滤数据集(换句话说,条件不起作用)。

SELECT Date, 
-- hits,
SUM(totals.transactions), 
SUM(totals.visits) 

FROM (

(
  SELECT date, totals,
    -- create own hits array
    ARRAY(
      SELECT AS STRUCT 
        hitnumber, 
        page,
        -- create own product array
        ARRAY(
          SELECT AS STRUCT productSku, productQuantity 
          FROM h.product AS p
          WHERE (SELECT COUNT(1)=0 FROM p.customDimensions WHERE index=6 AND value like '63%') 
        ) AS product
      FROM t.hits as h
      WHERE 
        NOT REGEXP_CONTAINS(page.pagePath,r'gebak|cake')
        AND
        (SELECT COUNT(1)=0 FROM h.customDimensions WHERE index=23 AND value like '%editor%')
    ) AS hits
  FROM
    `[projectID].[DatasetID].ga_sessions_*` t
  WHERE 
  _TABLE_SUFFIX BETWEEN '20181217'
  AND '20181217'
  AND totals.visits > 0
  ))
  GROUP BY Date

有谁知道如何实现所需的输出?

提前非常感谢!

注意:出于隐私考虑,projectID 和 datasetID 在两个查询中都被屏蔽了。

【问题讨论】:

你不能使用“REGEXP_EXTRACT”函数在where子句中添加这些条件吗? @MJK,我不这么认为,请参阅下面帖子中的评论以了解我的解释。 【参考方案1】:

自有数组方法

您可以通过在原始数据上使用子查询并将其输出反馈给数组函数来创建自己的匹配和产品数组。在这些子查询中,您可以过滤掉您的匹配和产品:

#standardsql
SELECT
  date,
  hits
  --SUM(totals.visits) AS Sessions,
  --SUM(totals.transactions) AS Transactions
FROM
  (
  SELECT 
    date, totals,
    -- create own hits array
    ARRAY(
      SELECT AS STRUCT 
        hitnumber, 
        page,
        -- create own product array
        ARRAY(
          SELECT AS STRUCT productSku, productQuantity 
          FROM h.product AS p
          WHERE (SELECT COUNT(1)=0 FROM p.customDimensions WHERE index=6 AND value like '63%') 
        ) AS product
      FROM t.hits as h
      WHERE 
        NOT REGEXP_CONTAINS(page.pagePath,r'gebak|cake')
        AND
        (SELECT COUNT(1)=0 FROM h.customDimensions WHERE index=23 AND value like '%editor%')
    ) AS hits
  FROM
    `bigquery-public-data.google_analytics_sample.ga_sessions_20161104` t
  )
--GROUP BY 1
LIMIT 100

我将此示例置于未分组状态,但您可以通过注释掉 hits 并相应地分组来轻松调整它...

细分方法

我认为您只需要在 WHERE 语句中使用正确的子查询:

#standardsql
SELECT
  date,
  SUM(totals.visits) AS Sessions,
  SUM(totals.transactions) AS Transactions
FROM
  `bigquery-public-data.google_analytics_sample.ga_sessions_*` t
WHERE
  (SELECT COUNT(1)=0 FROM t.hits h
    WHERE 
      (SELECT count(1)>0 FROM h.customDimensions WHERE index=23 AND value like '%editor%')
      OR
      (SELECT count(1)>0 from h.product p, p.customdimensions cd WHERE index=6 AND value like '63%')
      OR
      REGEXP_CONTAINS(page.pagePath,r'gebak|cake')
  )
GROUP BY date

由于您的所有组都在会话级别,因此您不需要在主表上进行任何展平(分别与数组交叉连接),这很昂贵。 在最外层的WHERE 中,您输入带有子查询的hits 数组——这就像一个for-each 行。这里已经可以统计REGEXP_CONTAINS(page.pagePath,r'gebak|cake')的次数了。

对于其他情况,您再次编写子查询以输入相应的数组 - 在第一种情况下,customDimensionshits 中。这就像一个嵌套在另一个中的 for-each(子查询中的子查询)。

在第二种情况下,我只是扁平化 - 但仅在子查询中:product 及其 customDimensions。所以这也是一次嵌套的 for-each,因为我很懒惰并且交叉加入。我本可以编写另一个子查询而不是交叉连接,所以基本上是一个三重嵌套的 for-each(子查询中的子查询)。

由于我在计算要排除的病例,所以我的外部条件是COUNT(1)=0

我只能用 ga 样本数据对其进行测试......所以它有点未经测试。但我想你明白了。

【讨论】:

非常感谢马丁的意见!然而不幸的是,结果并不是我所希望的。根据您提出的查询,我准确地复制了 GA 界面中的数字,但是以分段为基础的。但是现在过滤掉了太多的数据。例如。假设访问者点击了一个 URL 包含“蛋糕”的页面(应该过滤掉这个点击),但是在同一个会话中后来做了一个交易,上面提到的所有 3 个条件都通过了,我仍然希望包含这个交易。所以实际上我希望上述条件适用于基于命中,而不是基于会话。 进一步澄清:我的目标实际上是从 GA 视图重现数字,而不是加载到 BigQuery 的视图。上述条件用作此视图的过滤器。 为了重现会话级别的数据(因此没有提供所需的输出,请参阅我在上面评论中的输入)我使用了以下部分,请参阅此屏幕截图:i.stack.imgur.com/6JjcH.png 这意味着另一个视图不包括会话 - 可能是因为会话只有一个网页浏览?否则,我根本看不到过滤命中会如何影响这一点。你可以尝试添加AND hitnumber=1(只是为了估计)看看它是否更接近? 另一种视图不排除会话; GA 视图过滤器过滤掉命中级别的数据,而不是会话级别的数据。在您提供的查询中,排除了整个会话,其中 any hit 在会话中的 3 个条件之一确实适用(添加 hitnumber=1 不起作用,我在数据中看到也完整排除了许多点击的会话,以及我希望包含在数据中的点击)。但我只想排除适用 3 个条件之一的 hits。例如,如果一个会话有 40 个匹配项,则可能应根据条件排除 5 个匹配项并包含 35 个匹配项。【参考方案2】:

只是一个关于如何在公共集上使用 WITH 和 REGEXP_EXTRACT 的快速示例/想法

WITH CD6 AS (
SELECT cd.value, SUM(totals.visits) AS Sessions6Sum
FROM
  `bigquery-public-data.google_analytics_sample.ga_sessions_*`,
   UNNEST(hits) AS hits,
   UNNEST(hits.product) AS prod,
   UNNEST(prod.customDimensions) AS cd
   WHERE cd.index=6 
   AND NOT REGEXP_CONTAINS(cd.value,r'^63.....$')
   GROUP BY cd.value
),
CD23 AS (
SELECT cd.value, SUM(totals.visits) AS Sessions23Sum
FROM
  `bigquery-public-data.google_analytics_sample.ga_sessions_*`,
   UNNEST(hits) AS hits,
   UNNEST(hits.product) AS prod,
   UNNEST(prod.customDimensions) AS cd
   WHERE cd.index=23 
   AND NOT REGEXP_CONTAINS(cd.value,r'editor')
   GROUP BY cd.value
)

select CD6.Sessions6Sum + CD23.Sessions23Sum from CD6, CD23

您可以在bigQuery官方API page获取更多关于如何使用REGEXP_EXTRACT的信息

【讨论】:

我知道函数 REGEXP_EXTRACT,但这里的整个问题是 - 因为需要对命中和产品级别的自定义维度进行过滤 - 命中和产品需要 UNNEST()等级。但是看起来当我在产品级别取消嵌套时,无法再访问命中级别的自定义维度数据(如果我在这里错了,请纠正我)。 如果您可以编辑您的原始 sql 以更好地显示您的问题,它将有所帮助。我现在可以建议的是使用 WITH sql 使用不同的过滤器创建 3 个对象,然后从中选择您需要的数据 Tamir,在描述部分我现在添加了完整的查询,但没有产生所需的输出。如您所见,我执行了几个 UNNEST() 来访问产品和命中级别。 我根据您的 SQL 编辑我的示例。你仍然需要根据你的需要调整它,但我希望它的方向是你解决问题所需要的 感谢 Tamir 提供查询。然而,不幸的是,这不起作用。由于 UNNESTING(),SUM(totals.visits) 比 Google Analytics UI 中显示的值高出 10 倍以上。这可能是因为在生成的数据集中,记录处于命中/产品级别,但 totals.visits 已经显示为会话的聚合(也适用于命中/产品行)。我不太确定如何在您提供的查询中解决这个问题。顺便说一句,这也是我上面提供的原始查询中的一个问题。

以上是关于BigQuery:根据匹配和产品范围维度过滤掉匹配的主要内容,如果未能解决你的问题,请参考以下文章

取消嵌套命中和取消嵌套会话范围的自定义维度 BigQuery 代码过滤器

取消自定义维度的嵌套时,GA 网页浏览量与 BigQuery 不匹配?

Js正则表达式的如何写这样一个匹配规则!1) 取指定范围的内容 2)过滤指定范围的内容

在 Bigquery 中,如何使用标准 Sql 过滤 Struct 数组以匹配 Struct 中的多个字段?

如何过滤掉单个项目,而不仅仅是在行和列的基础上?

BigQuery 根据最接近的时间戳和匹配值组合表