考虑这两个表
CREATE OR REPLACE TABLE `test.items` AS (
SELECT 1 AS ID, 1 AS Foo, 100 AS Bar,
UNION ALL SELECT 2 AS ID, 1 AS Foo, 155 AS Bar,
UNION ALL SELECT 3 AS ID, 1 AS Foo, 219 AS Bar,
UNION ALL SELECT 4 AS ID, 2 AS Foo, 155 AS Bar,
UNION ALL SELECT 5 AS ID, 2 AS Foo, 200 AS Bar,
UNION ALL SELECT 6 AS ID, 2 AS Foo, 300 AS Bar
);
CREATE OR REPLACE TABLE `test.conditions` AS (
SELECT 1 AS Foo, ["50..150", "2**"] AS Conditions,
UNION ALL SELECT 2 AS Foo, ["3*0", "200..300", "155"] AS Conditions
)
我正在尝试设计一个类似于将 items 左连接到 conditions 的查询(保留每个条件并且仅保留匹配的项目)。
Foo
列必须匹配Bar
中的
items
列可以匹配Conditions
数组中的任意条件
为了增加复杂性,
Conditions
使用了非标准语法,其中
M..N
表示“匹配从 M 到 N(含)的任何内容M*N
表示“匹配任何以 M 开头、以 N 结尾的 3 字符字符串”M**
表示“匹配任何以 M 开头的 3 字符字符串”我很乐意将这种逻辑语法转换为正则表达式,但我正在努力构建查询设计。我猜我应该使用 LOGICAL_OR 和 UDF..类似
WITH step1 AS (
SELECT
Foo,
Bar,
Conditions
FROM `test.conditions`
LEFT JOIN `test.items` USING(Foo)
)
SELECT * FROM step1 WHERE (LOGICAL_OR(MyFunc(Bar, Conditions)))
参见示例。 PostgreSql 方言。
with cond as(
select foo,c
,case when c like '%..%' then
cast(left(c,position('..' in c)-1) as int)
when c not like '%*%' then cast(c as int)
end i1
,case when c like '%..%' then
cast(substring(c,position('..' in c)+2,100) as int)
when c not like '%*%' then cast(c as int)
end i2
,case when c like '%*%' then replace(c,'*','%')
end p1
from(
select foo,unnest(conditions)c from test_conditions
)x
)
select *
,case when i.bar between c.i1 and c.i2 then 1
when cast(bar as varchar) like p1 then 1
else 0
end fl
from test_items i
left join cond c on i.foo=c.foo