如何制作可在单个列上运行的可重用UDF?

时间:2016-10-28 01:43:35

标签: google-bigquery google-cloud-platform

而不是像

那样编写查询
select * from xyz where mydomain IN ('foobar.com', 'www.example.com')

我想写一个像

这样的函数
select * from xyz where one_of_my_domains(select mydomain as from_site)

但是我希望能够将这些函数重用于许多表中的任何一个url。目前,当我使用这样的函数时,我必须预定义返回的内容并在SQL语句的整个FROM部分使用它。有没有办法将UDF推广到我只能在1列上使用它而不是在所有行上操作的地方。这是我的代码现在可以工作,但我必须预定义每个输出列,使其不可重用。

domains = ['foobar.com', 'www.example.com'];

// The UDF
function has_domain(row, emit) {
  var has_domain = false;
  if (row.to_site !== null && row.to_site !== undefined) {
    for (var i = 0; i < domains.length; i++){
    if (domains[i] === String.prototype.toLowerCase.call(row.to_site)){
      has_domain = true;
      break;
     }
   }
  }
  return emit({has_domain: has_domain, trackingEventId: row.trackingEventId, date: row.date, from_site: row.from_site, to_site: row.to_site});
}


// UDF registration
bigquery.defineFunction(
  'has_domain',  // Name used to call the function from SQL

  ['from_site'],  // Input column names

  // JSON representation of the output schema
  [{name: 'has_domain', type: 'boolean'}],

  has_domain  // The function reference
);

2 个答案:

答案 0 :(得分:2)

它可能看起来有点乱 - 但下面的确是你所要求的! 确保您使用的是标准SQL(请参阅Enabling Standard SQL

CREATE TEMPORARY FUNCTION one_of_my_domains(x STRING, a ARRAY<STRING>)
  RETURNS BOOLEAN AS
  (x IN (SELECT * FROM UNNEST(a)));

WITH xyz AS (
  SELECT 1 AS id, 'foobar.com' AS mydomain UNION ALL
  SELECT 2 AS id, 'www.google.com' AS mydomain
), 
site AS (
  SELECT 'foobar.com' AS domain UNION ALL
  SELECT 'www.example.com' AS domain
)
SELECT * 
FROM xyz 
WHERE one_of_my_domains(mydomain, ARRAY((SELECT domain FROM site)))

答案 1 :(得分:1)

您正在使用scalar UDFs寻找standard SQL。与遗留SQL相比,它们使用起来不那么尴尬了。