【问题标题】:Lead & Analytical Functions in BigQueryBigQuery 中的潜在客户和分析功能
【发布时间】:2018-12-11 16:22:20
【问题描述】:

假设我的桌子是这样的

我正在尝试使用此信息修改我的表格

我添加了两列,其中WhenWasLastBasicSubjectDone 列将让您知道学生在哪个学期完成了他最新的基础课程(按学期排序)。另一栏TotalBasicSubjectsDoneTillNow说明了学生到现在为止完成了基础课程(学科)多少次(按学期排序)?

我认为使用 Joins 和 UDF 很容易解决这个问题,但我想利用 BigQuery 中现有分析函数的强大功能并在没有连接的情况下解决它。

【问题讨论】:

  • SQL 表代表 无序 集。除非列指定该顺序,否则没有“以前的”或“直到现在”。那一栏是semester吗?
  • @GordonLinoff 感谢您的评论。列学期已经排序(按升序排列)

标签: sql performance join google-bigquery state


【解决方案1】:

以下是 BigQuery 标准 SQL

#standardSQL
SELECT *,
  LAST_VALUE(IF(subject='Basic',semester,NULL) IGNORE NULLS) OVER(win) AS WhenWasLastBasicSubjectDone ,
  COUNTIF(subject='Basic') OVER(win) AS TotalBasicSubjectsDoneTillNow     
FROM `project.dataset.table`
WINDOW win AS (PARTITION BY student ORDER BY semester)

您可以使用您问题中的虚拟数据进行测试,如下所示

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 1 Student, 'Sub1' Subject, 'Sem1' Semester UNION ALL
  SELECT 1, 'Sub2', 'Sem2' UNION ALL
  SELECT 1, 'Basic', 'Sem3' UNION ALL
  SELECT 1, 'Basic', 'Sem4' UNION ALL
  SELECT 1, 'Sub3', 'Sem5' UNION ALL
  SELECT 1, 'Sub2', 'Sem6' UNION ALL
  SELECT 1, 'Sub3', 'Sem7' UNION ALL
  SELECT 1, 'Sub4', 'Sem8' 
)
SELECT *,
  LAST_VALUE(IF(subject='Basic',semester,NULL) IGNORE NULLS) OVER(win) AS WhenWasLastBasicSubjectDone ,
  COUNTIF(subject='Basic') OVER(win) AS TotalBasicSubjectsDoneTillNow     
FROM `project.dataset.table`
WINDOW win AS (PARTITION BY student ORDER BY semester)
-- ORDER BY Semester

【讨论】:

  • 谢谢@Mikhail .. 我可以通过使用 OVER 来思考——对于每条记录,我们将检查该分区中所有先前的值,使其复杂度为 O(n*n) .. 但是在 UDF 的帮助下,我可以在 O(n) 中解决它。但是 UDF 的问题是在 BigQuery 中注册 UDF 需要 7-8 秒,这非常大。你对此有什么想法吗?
  • 在这种情况下,推荐使用分析/窗口函数。就我个人而言,我将 UDF 用作最后的手段,例如当逻辑需要递归时。有关此类案例的示例,请参阅我昨天的答案之一
  • 您能否确认这是在 O(n*n) 还是 O(n) 中求解?由于我的数据集大小以十亿为单位,我想更好地了解复杂性,以便提高查询性能。
  • 我建议尝试您拥有的任何选项并选择最好的一个 :o) 确认 - 我将这个留给谷歌确认
【解决方案2】:

您可以为此使用窗口函数——假设您有一个指定排序的列。让我假设该列是semester

select t.*,
       max( case when subject = 'Basic' then semester end ) over (partition by student order by semester end) as lastbasic,
       sum( case when subject = 'Basic' then 1 else 0 end ) over (partition by student order by semester end) as numbasictillnow    
from t

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-20
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 2021-01-08
    • 2022-08-16
    • 1970-01-01
    相关资源
    最近更新 更多