【问题标题】:Sumproduct in SQL that offsets each rowSQL 中的 Sumproduct 偏移每一行
【发布时间】:2020-02-02 06:47:15
【问题描述】:

我正在将一些计算从 Google 表格迁移到 BigQuery,并且需要编写一个 SUMPRODUCT 脚本来偏移每一行。

这是 Google 表格中的数据。 Column_1, Column_2 给定,SUMPRODUCT 是一个计算:

Column_1 Column_2 SUMPRODUCT
   0         1        0
   5         0        10
   0         1        0
   5         0        5

第 1 列从单元格 A1 开始。

每一行的SUMPRODUCT公式如下:

=SUMPRODUCT(A2:A5,$B$2:$B$5)
=SUMPRODUCT(A3:A6,$B$2:$B$5)
=SUMPRODUCT(A4:A7,$B$2:$B$5)
=SUMPRODUCT(A5:A8,$B$2:$B$5)

在 Biquery 中,我可以使用 SELECT SUM (column_1 * column_2) AS SUMPRODUCT FROM Table_1 创建第一个 SUMPRODUCT 行

在此之后,每行偏移第 1 列数组具有挑战性。我的最终数据集将有 500 多行我需要这样做。我也尝试过在 SQL 中使用 OFFSET 函数,但遇到了错误。

【问题讨论】:

    标签: sql google-bigquery sumproduct


    【解决方案1】:

    以下是 BigQuery 标准 SQL

    #standardSQL
    WITH `project.dataset.table` AS (
      SELECT 0 pos, 0 Column_1, 1 Column_2 UNION ALL
      SELECT 1, 5, 0 UNION ALL
      SELECT 2, 0, 1 UNION ALL
      SELECT 3, 5, 0 
    ), b AS (
      SELECT pos, Column_2 FROM `project.dataset.table`
    )
    SELECT 
      pos, Column_1, Column_2,
      (SELECT SUM(Column_1 * Column_2)
        FROM UNNEST(a) WITH OFFSET AS pos
        JOIN b USING(pos)  
      ) SUMPRODUCT
    FROM (
      SELECT *, 
        ARRAY_AGG(Column_1) OVER(ORDER BY pos ROWS BETWEEN CURRENT ROW AND 3 FOLLOWING) a
      FROM `project.dataset.table` t
    )
    

    结果

    Row pos Column_1    Column_2    SUMPRODUCT   
    1   0   0           1           0    
    2   1   5           0           10   
    3   2   0           1           0    
    4   3   5           0           5    
    

    正如您从上面看到的 - 您必须有一些字段将在工作表中扮演行号的角色 - 在我的回答中,我使用 pos 列作为示例

    【讨论】:

      【解决方案2】:

      作为与@Mikhail 的回答略有不同的方法,您可以使用 BigQuery 中提供的基于 JS 的外部 UDF 来简化这些任务:

      CREATE TEMP FUNCTION sumproduct(column_1 array<int64>, column_2 array<int64>)
      RETURNS int64
      LANGUAGE js AS """
        output = 0;
        for (var i=0; i<column_1.length; i++){
           output += (column_1[i]*column_2[i]);
        }
        return output;
      """;
      
      with sumproducts as (
        select 
           row_number() over () as idx, 
           sumproduct(aggs, b) as sp from (
              select 
                 array_agg(column_1) over (order by idx rows between current row and 3 following) aggs, 
                 array_agg(column_2) over () b 
              from (
                 select row_number() over () as idx, column_1, column_2 from `dataset.table`
              )
           )
      ),
      items as (
         select row_number() over() as idx, column_1, column_2 from `dataset.table`
      )
      
      select r.column_1, r.column_2, spd.sp from items r join sumproducts spd on r.idx = spd.idx
      

      希望对你有帮助。

      【讨论】:

        猜你喜欢
        • 2010-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-30
        • 2016-04-13
        • 1970-01-01
        相关资源
        最近更新 更多