表值作为SQL函数的输入

时间:2018-01-09 01:12:23

标签: mysql sql-server oracle11g google-bigquery

我试图将表的所有值用作SQL定义函数的输入。

SELECT Field1,  REGEXP_CONTAINS(Field1, (SELECT Field2 FROM table2)) FROM table1;

这个在大查询中返回错误,因为:

  1. 子查询不能用作输入和
  2. 它返回超过1行。
  3. 是否可以告诉我是否有办法将一个表的所有值用作单个函数的输入。

    致以最诚挚的问候,

3 个答案:

答案 0 :(得分:2)

下面的示例适用于BigQuery Standard SQL

    
#standardSQL
SELECT 
  Field1, STRING_AGG(Field2) AS contained
FROM `table1`
JOIN `table2`
ON REGEXP_CONTAINS(Field1, Field2) 
GROUP BY Field1  

您可以使用以下虚拟数据

来测试/播放上面的内容
#standardSQL
WITH `table1` AS (
  SELECT 'abc' Field1 UNION ALL
  SELECT 'xyz'
),
`table2` AS (
  SELECT 'a' Field2 UNION ALL
  SELECT 'x' UNION ALL
  SELECT 'y' UNION ALL
  SELECT 'z'
)
SELECT 
  Field1, STRING_AGG(Field2) AS contained
FROM `table1`
JOIN `table2`
ON REGEXP_CONTAINS(Field1, Field2) 
GROUP BY Field1

结果为

Field1  contained    
abc     a    
xyz     x,y,z    
  

第二个选项更符合您原来的期望(就其而言   语法模式)但需要使用SQL UDF

#standardSQL
CREATE TEMP FUNCTION Check_Contains(str STRING, arr ARRAY<STRING>) AS ((
  SELECT STRING_AGG(item) AS contained
  FROM UNNEST(arr) item
  WHERE REGEXP_CONTAINS(str, item) 
));
SELECT Field1, 
  Check_Contains(Field1, ARRAY(SELECT Field2 FROM `table2`)) AS contained
FROM `table1`   

要测试/播放 - 您可以使用以下

#standardSQL
CREATE TEMP FUNCTION Check_Contains(str STRING, arr ARRAY<STRING>) AS ((
  SELECT STRING_AGG(item) AS contained
  FROM UNNEST(arr) item
  WHERE REGEXP_CONTAINS(str, item) 
));
WITH `table1` AS (
  SELECT 'abc' Field1 UNION ALL
  SELECT 'xyz' UNION ALL
  SELECT 'vwu'
),
`table2` AS (
  SELECT 'a' Field2 UNION ALL
  SELECT 'x' UNION ALL
  SELECT 'y' UNION ALL
  SELECT 'z'
)
SELECT Field1, 
  Check_Contains(Field1, ARRAY(SELECT Field2 FROM `table2`)) AS contained
FROM `table1`  

输出为

Field1  contained    
abc     a    
xyz     x,y,z    
vwu     null     
  

还有一个选项(没有UDF)

#standardSQL
SELECT Field1, 
  ARRAY_TO_STRING(REGEXP_EXTRACT_ALL(Field1, (SELECT STRING_AGG(Field2, '|') FROM `table2`)), ',') AS contained
FROM `table1`   

你可以使用与上面相同的虚拟数据(前两个选项)

答案 1 :(得分:1)

您需要使用CROSS JOIN代替。请注意,如果表很大,这将会很慢,因为您正在获取所有行的叉积:

SELECT
  t1.Field1,
  REGEXP_CONTAINS(t1.Field1, t2.Field2)
FROM table1 AS t1
CROSS JOIN table2 AS t2;

如果您想知道此表达式为true的所有Field1 / Field2对,您可以使用带过滤器的查询:

SELECT
  t1.Field1,
  t2.Field2
FROM table1 AS t1
CROSS JOIN table2 AS t2
WHERE REGEXP_CONTAINS(t1.Field1, t2.Field2);

答案 2 :(得分:0)

谢谢大家的回答。 我有一个类似于大查询的版本,最后使用了接近你的建议的以下代码。

WITH table1 AS (SELECT field1 FROM UNNEST(['value1', ...'value2']) AS field1),
table2 AS (SELECT field2 FROM UNNEST(['v1', 'v2']) AS field2)
SELECT
field1,
(SELECT LOGICAL_OR(REGEXP_CONTAINS(field1, CONCAT(r'(?i)\b', field2, r'\b'))) FROM table2) AS has_table2_match
FROM
table1

再次感谢您的建议。欣赏它。