BigQuery JavaScript UDF 使用 SQL 查询中的值调用数组

Posted

技术标签:

【中文标题】BigQuery JavaScript UDF 使用 SQL 查询中的值调用数组【英文标题】:BigQuery JavaScript UDF to call Array with values from SQL query 【发布时间】:2021-05-30 02:45:58 【问题描述】:

我正在尝试编写我的第一个 Bigquery UDF 函数(转换 Oracle 函数),感谢 SO 的帮助,到目前为止我能够编写部分代码,如下所示,

我的任务是,当我们传递了诸如 admission_date、input1、input2 之类的参数时,应该根据少数计算(而不是周末或节假日)来计算出院日期。

对任何错误或任何麻烦表示歉意

这是我的代码:

    DECLARE list ARRAY <STRING>;
    DECLARE v_holiday STRING DEFAULT 'No';
    DECLARE v_due_report INT64;
    DECLARE v_due_report_cnt INT64;
    DECLARE v_days INT64;
    DECLARE p_date DATE;
    DECLARE p_input1 STRING;
    DECLARE p_input2 STRING;
    DECLARE v_bus_day STRING;
    DECLARE v_cnt INT64 DEFAULT 1;
    DECLARE v_max_days INT64 DEFAULT 1;
    
    #SET v_holiday = (SELECT CASE WHEN EXISTS (SELECT 1 FROM `examples.date_calendar` WHERE HOLIDAY = DATE(p_date)) THEN 'Yes' ELSE 'No' END);
    
    select ARRAY(SELECT holiday from `examples.date_calendar`) AS list;
    
    SET v_due_report_cnt = (SELECT COUNT(*) FROM `examples.report_assessments` WHERE p_date BETWEEN START_DATE AND END_DATE 
                                    AND p_input1 = ICD_9_CLASS AND p_input2 = LAST_MEDICATION);
    
    CREATE TEMP FUNCTION patient_report_date(p_admit_date DATE, p_input1 STRING,p_input2 STRING)
     RETURNS STRING
     LANGUAGE js AS """
         var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
         var dayName = days[p_admit_date.getDay()];
    
        if(p_admit_date < Date.parse("2016-02-01") 
                v_bus_day = p_admit_date.setDate(date.getDate() + 2);
                return v_bus_day;
          
    
        # SET v_HOLIDAY = (SELECT CASE WHEN EXISTS (SELECT 1 FROM `examples.date_calendar` WHERE HOLIDAY = TRUNC(p_admit_date)) THEN 'Yes' ELSE 'No' END)
    
          if(!(dayName) in ('Saturday', 'Sunday')) && (v_holiday == 'No')
              v_days = 2;
          
           else  
               v_days = 3;
                          p_date_trunc_time = new Date(p_date.getFullYear(), p_date.getMonth(), p_date.getDate());
           v_bus_day = new Date(p_date_trunc_time.setSeconds(p_date_trunc_time.getSeconds() + 1));
          
    
           if(p_admit_date < Date.parse("2020-07-01") 
               v_due_report = 0
           
          #SET v_due_report_cnt = (SELECT COUNT(*) FROM `examples.report_assessments` WHERE p_admit_date BETWEEN START_DATE AND END_DATE 
                                    #AND p_input1 = ICD_9_CLASS AND p_input2 = LAST_MEDICATION);
            else if (v_due_report_cnt > 0) 
                  v_due_report = 4
                 
          v_days = v_days + v_due_report;    
    
        while max_days <= v_days 
            if (! days[(p_admit_date + day).getDay()] in ('Saturday','Sunday') && (list.indexOf(p_admit_date)==-1) 
                v_cnt++
                max_days++
             
            day++
           
        
    
    v_bus_day = p_admit_date + v_vcnt;
    
     return v_bus_day
    
    """;
WITH data_date AS (
  SELECT DATE("2021-05-31") AS p_DATE, "ICD8081" AS p_input1, "CDE2" AS p_input2 UNION ALL
  SELECT DATE("2021-05-30"),"ICD8211","DER2"
)
SELECT p_DATE,
       p_input1,
       p_input2,
  patient_report_date(p_DATE,p_input1,p_input2) discharge_date
FROM data_date; 

当我执行该函数时,它向我抛出了错误“SyntaxError: Unexpected Token” 对此代码的任何建议或反馈都会有所帮助。 感谢您的帮助 感谢您阅读我的帖子。

更新的代码:最后,我能够让我的代码正常工作,我想添加 SO,所以它可能对某人有用。

DECLARE holiday_list ARRAY <STRING>;
DECLARE holiday_weekend ARRAY <STRING>;
DECLARE report_assessments ARRAY <STRUCT<ICD_9_CLASS STRING,LAST_MEDICATION STRING>>;
DECLARE p_admit_date DATE;
DECLARE p_input1 STRING;
DECLARE p_input2 STRING;
   
SET holiday_list =  (SELECT ARRAY(SELECT CAST(holiday AS STRING) FROM `examples.date_calendar`)); 
SET v_due_report = (SELECT ARRAY(SELECT STRUCT(CAST(ICD_9_CLASS AS STRING) AS ICD_9_CLASS, CAST(LAST_MEDICATION AS STRING) AS LAST_MEDICATION) FROM `examples.report_assessments`));
    
CREATE TEMP FUNCTION patient_report_date(p_admit_date DATE, p_input1 STRING,p_input2 STRING)
   RETURNS STRING
     LANGUAGE js AS """
        var days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
        var holiday_weekend = ['Saturday','Sunday'];
        var v_signature=0;
        var v_days=0;
        var v_day =1;
        var v_cnt=0;
        var v_max_days=1;
    
        if(p_admit_date < new Date("2016-02-01")) 
                 p_admit_date.setDate(p_admit_date.getDate() + 2); 
                
        else 
            
              if((holiday_weekend.indexOf(days[p_admit_date.getDay()]) === -1) && (holiday_list.indexOf(p_admit_date) === -1)) 
                    v_days = 2; 
                    
              else 
                    v_days = 3;
                    
    
              for(var i = 0; i < report_assessments.length; i++) 
                    if ((report_assessments[i]['ICD_9_CLASS'] === p_input1)  && (signature_assessments[i]['LAST_MEDICATION'] === p_input2))  
                        v_signature++; 
                   
               
            
             if (p_admit_date < Date("2020-07-01") && (v_signature === 0)) 
                    v_days = v_days; 
                    
             else if (v_signature > 0) 
                    v_days = v_days + 4; 
                    

             function addDays(date, days) 
             var result = new Date(date);
             result.setDate(result.getDate() + days);
             return result;
            
            while max_days <= v_days 
                if ((holiday_list.indexOf(addDays(p_admit_date,v_day).toISOString().slice(0, 10)) === -1) && (holiday_weekend.indexOf(days[addDays(p_admit_date,v_day).getUTCDay()]) === -1))  
                    v_max_days++;
                      
                v_day++;
                v_cnt++;
                 
            p_admit_date.setDate(p_admit_date.getDate() + v_cnt); 
             

        return  p_admit_date;
    
    """;
    
WITH data_date AS (
  SELECT DATE("2021-05-31") AS p_DATE, "ICD8081" AS p_input1, "CDE2" AS p_input2,holiday_list, report_assessments UNION ALL
  SELECT DATE("2021-05-30"),"ICD8211","DER2",holiday_list, report_assessments
)
SELECT p_DATE,
       p_input1,
       p_input2,
  patient_report_date(p_DATE,p_input1,p_input2,holiday_list, report_assessments) discharge_date
FROM `examples.tabledata`; ```

【问题讨论】:

【参考方案1】:

是的,javascript UDF 是 also persistent。只需删除 TEMP 并选择指定项目名称和数据集名称:

CREATE FUNCTION project_name.dataset_name.patient_report_date(...)

【讨论】:

谢谢@Sergey,我想将值从上面的数组传递到UDF JavaScript UDF 也可以接收数组 - cloud.google.com/bigquery/docs/reference/standard-sql/… 示例 - ***.com/questions/65738242/… 非常感谢 Sergey,我可以使用list.indexOf(p_admit_date)==-1 来检查上面声明的数组中是否存在日期 我已经用示例选择语句更新了代码,当我在 BigQuery 中执行时它失败并且不知道如何调试,你能帮我解决这个问题

以上是关于BigQuery JavaScript UDF 使用 SQL 查询中的值调用数组的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery JavaScript UDF:V8 实例的区域

用于合并值列表/数组的 BigQuery JavaScript UDF

描述如何在 SQL 中内联定义 Javascript UDF 函数的 BigQuery 文档在哪里(不是在 UDF 编辑器或单独的文件中)?

使用 JavaScript BigQuery UDF 解密/解码 AES256 [重复]

用于 BigQuery UDF 的纯 javascript HTML 解析器

在 google bigquery 中,如何使用 google python 客户端使用 javascript UDF