Google bigquery 在BigQuery中,什么是OTRANSLATE的等价物?

Google bigquery 在BigQuery中,什么是OTRANSLATE的等价物?,google-bigquery,teradata,bigquery-standard-sql,Google Bigquery,Teradata,Bigquery Standard Sql,我正在尝试将一个查询转换为在BigQuery中运行,该查询使用来自Teradata的。比如说, SELECT OTRANSLATE(text, 'ehlo', 'EHLO') FROM ( SELECT 'hello world' AS text UNION ALL SELECT 'elliott' ); 这应产生: HELLO wOrLd ELLiOtt 有没有办法在BigQuery中表达这个函数?看起来没有直接等价物。是的,您可以使用字符串上的数组操作来实现这一点。这里有一个解决

我正在尝试将一个查询转换为在BigQuery中运行,该查询使用来自Teradata的。比如说,

SELECT OTRANSLATE(text, 'ehlo', 'EHLO')
FROM (
  SELECT 'hello world' AS text UNION ALL
  SELECT 'elliott'
);
这应产生:

HELLO wOrLd
ELLiOtt

有没有办法在BigQuery中表达这个函数?看起来没有直接等价物。

是的,您可以使用字符串上的数组操作来实现这一点。这里有一个解决方案:

CREATE TEMP FUNCTION OTRANSLATE(s STRING, key STRING, value STRING) AS (
  (SELECT
     STRING_AGG(
       IFNULL(
         (SELECT value[OFFSET(
            SELECT o FROM UNNEST(SPLIT(key, '')) AS k WITH OFFSET o2
            WHERE k = c)]
         ),
         c),
       '' ORDER BY o1)
   FROM UNNEST(SPLIT(s, '')) AS c WITH OFFSET o1)
  )
);

SELECT OTRANSLATE(text, 'ehlo', 'EHLO')
FROM (
  SELECT 'hello world' AS text UNION ALL
  SELECT 'elliott'
);
其思想是在值字符串中的键字符串的相同位置查找字符。如果键字符串中没有匹配的字符,我们将得到一个空偏移量,因此IFNULL的第二个参数将导致它返回未映射的字符。然后我们聚合回一个字符串,按字符偏移量排序

编辑:这里有一个变量也处理键和值长度的差异:

CREATE TEMP FUNCTION otranslate(s STRING, key STRING, value STRING) AS (
  IF(LENGTH(key) < LENGTH(value) OR LENGTH(s) < LENGTH(key), s,
  (SELECT
     STRING_AGG(
       IFNULL(
         (SELECT ARRAY_CONCAT([c], SPLIT(value, ''))[SAFE_OFFSET((
            SELECT IFNULL(MIN(o2) + 1, 0) FROM UNNEST(SPLIT(key, '')) AS k WITH OFFSET o2
            WHERE k = c))]
         ),
         ''),
       '' ORDER BY o1)
   FROM UNNEST(SPLIT(s, '')) AS c WITH OFFSET o1
  ))
);
SELECT
  otranslate("hello world", "", "EHLO") AS empty_from, -- 'hello world'
  otranslate("hello world", "hello world1", "EHLO") AS larger_from_than_source, -- 'hello world'
  otranslate("hello world", "ehlo", "EHLO") AS equal_size_from_to, -- 'HELLO wOrLd'
  otranslate("hello world", "ehlo", "EH") AS larger_size_from, -- 'HE wrd'
  otranslate("hello world", "ehlo", "EHLOPQ") AS larger_size_to, -- 'hello world'
  otranslate("hello world", "ehlo", "") AS empty_to; -- 'wrd'

另一种稍有不同的方法是BigQuery标准SQL

#standardSQL
CREATE TEMP FUNCTION OTRANSLATE(text STRING, from_string STRING, to_string STRING) AS ((
  SELECT STRING_AGG(IFNULL(y, a), '' ORDER BY pos)
  FROM UNNEST(SPLIT(text, '')) a WITH OFFSET pos
  LEFT JOIN (
    SELECT x, y
    FROM UNNEST(SPLIT(from_string, '')) x WITH OFFSET
    JOIN UNNEST(SPLIT(to_string, '')) y WITH OFFSET
    USING(OFFSET)
  )
  ON a = x
));
WITH `project.dataset.table` AS (
  SELECT 'hello world' AS text UNION ALL
  SELECT 'elliott'
)
SELECT text, OTRANSLATE(text, 'ehlo', 'EHLO') as new_text
FROM `project.dataset.table`   
有输出

Row     text            new_text     
1       hello world     HELLO wOrLd  
2       elliott         ELLiOtt   
注:以上版本假定from和to字符串长度相等,from字符串中没有重复字符

更新以跟踪BigQuery中该函数版本的扩展期望

结果

Row empty_from  larger_from_than_source equal_size_from_to  larger_size_from    larger_size_to  empty_to     
1   hello world EHLLL                   HELLO wOrLd             HE wrd          HELLO wOrLd     wrd    
.   
注意:此函数的Teradata版本是递归的,因此当前的实现不是Teradata的OTRANSLATE的精确实现

teradata文档中的使用说明 如果from_字符串中的第一个字符出现在源_字符串中,则所有出现的字符都将替换为to_字符串中的第一个字符。这将对from_字符串中的所有字符和from_字符串中的所有字符重复。替换是逐字符执行的,也就是说,第二个字符的替换是在替换第一个字符后产生的字符串上进行的

这可以很容易地用JSUDF实现,这很简单,我想我不会朝这个方向走:o

类似于
Row empty_from  larger_from_than_source equal_size_from_to  larger_size_from    larger_size_to  empty_to     
1   hello world EHLLL                   HELLO wOrLd             HE wrd          HELLO wOrLd     wrd    
.