根据行值填充列 BigQuery 标准 SQL

Posted

技术标签:

【中文标题】根据行值填充列 BigQuery 标准 SQL【英文标题】:Populate column based on row values BigQuery Standard SQL 【发布时间】:2020-08-05 06:23:58 【问题描述】:

我有一张桌子让我们说:-

  Name   A    B    C    D    
------- ---  ---  ---  --- 
 alpha   0    1    0   0.6     
 beta   0.6   0    0   0.1
 gama    0    0    0   0.6

现在我想根据 A、B、C、D 值在两列(Result & Class) 上填充值。

条件是,如果任何字段(A、B、C、D)中的值>.5,那么Result 列应该有“F”,否则应该有“P”。 valie >.5 的列也应该在Class example("A,D")

为了更好地理解这里是我想要的结果:-

  Name   A    B    C    D    Result    Class
------- ---  ---  ---  ---  --------  -------
 alpha   0    1    0   0.6     F        B,D      
 beta   0.6   0    0   0.1     F         A
 gama    0    0    0   0.4     P        NULL 

我是 BigQuery 新手,需要帮助。有什么解决方法。

这是我迄今为止所做的事情

  SELECT *, CASE WHEN (A > .5 OR B > .5 OR C > .5 OR D >.5)
            THEN 'F'
            ELSE 'P' END AS Result AND Class....//here i am stuck
  
  FROM table1

实际上,我不知道如何构建这个确切的脚本。我能够实现第一部分,我能够用“F”和“P”填充结果列,但不能让类填充列名....

【问题讨论】:

希望我的问题很清楚。 【参考方案1】:

由于您正在分析每一列,我假设您没有大量的列。因此,我创建了一个简单的javascript User Defined Function (UDF) 来检查行的值并在满足条件时返回列的名称。

我已使用提供的示例数据来测试以下查询。

#javaScript UDF
CREATE TEMP FUNCTION class(A FLOAT64, B FLOAT64, C FLOAT64, D FLOAT64)
RETURNS String
LANGUAGE js AS """
var class_array=[];
if(A > 0.5)class_array.push("A");
if(B > 0.5)class_array.push("B");
if(C > 0.5)class_array.push("C");
if(D > 0.5)class_array.push("D"); 

return class_array;
""";

#sample data
WITH data as (
 SELECT "alpha" as Name, 0 as A, 1 as B, 0 as C, 0.6 as D UNION ALL  
 SELECT "beta", 0.6, 0, 0, 0.1 UNION ALL
 SELECT "gama", 0, 0, 0, 0.4
)

Select name, A,B,C,D, 
        CASE WHEN (A > .5 OR B > .5 OR C > .5 OR D >.5) THEN "F" ELSE "P" END AS Result,
        IF(class(A,B,C,D) is null , null, class(A,B,C,D)) as Class from data

还有输出,

Row name    A   B   C   D   Result  Class
1   alpha   0   1   0   0.6 F       B,D
2   beta    0.6 0   0   0.1 F       A
3   gama    0   0   0   0.4 P   

正如 UDF 中所示,每行的值都会被分析,如果满足条件,列的名称会手动添加到字符串数组中。另外,请注意 JS UDF 返回的是字符串,而不是数组。它会自动将之前创建的 Array 转换为 String。

最后,我应该指出,在这种情况下,无法在查询中检索列名。虽然,您可以在其他情况下使用INFORMATION_SCHEMA 检索它。

【讨论】:

我最多有 5500 行,希望这不会超时。【参考方案2】:

以下是 BigQuery 标准 SQL

在许多情况下使用 javaScript UDF 会有所帮助,但如果可以使用 SQL 解决问题,如下例所示,则应避免使用

#standardSQL
SELECT *,
  ( SELECT IF(LOGICAL_OR(val > 0.5), 'F', 'P') 
    FROM UNNEST([A,B,C,D]) val
  ) AS Result,
  ( SELECT STRING_AGG(['A','B','C','D'][OFFSET(pos)]) 
    FROM UNNEST([A,B,C,D]) val WITH OFFSET pos 
    WHERE val > 0.5
  ) AS Class
FROM `project.dataset.table`  

您可以使用来自我们问题的示例数据进行测试,如下例所示

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 'alpha' name, 0 A, 1 B, 0 C, 0.6 D UNION ALL
  SELECT 'beta', 0.6, 0, 0, 0.1 UNION ALL
  SELECT 'gamma', 0, 0, 0, 0.4 
)
SELECT *,
  ( SELECT IF(LOGICAL_OR(val > 0.5), 'F', 'P') 
    FROM UNNEST([A,B,C,D]) val
  ) AS Result,
  ( SELECT STRING_AGG(['A','B','C','D'][OFFSET(pos)]) 
    FROM UNNEST([A,B,C,D]) val WITH OFFSET pos 
    WHERE val > 0.5
  ) AS Class
FROM `project.dataset.table`    

输出为

Row name    A       B   C   D       Result  Class    
1   alpha   0.0     1   0   0.6     F       B,D  
2   beta    0.6     0   0   0.1     F       A    
3   gamma   0.0     0   0   0.4     P       null       

【讨论】:

以上是关于根据行值填充列 BigQuery 标准 SQL的主要内容,如果未能解决你的问题,请参考以下文章

Mysql根据不同的行更新表中的行值

基于列值向sql中的列添加行值

如何在遍历熊猫数据框时创建新列并插入行值

根据同一行中的行值逐行更新列值

根据数据框中的其他行值创建列

PHP MySQL根据列/行值选择多个表