如何连接表 A 和 B,其中 A 中的每一行都包含要在 B 中匹配的逻辑条件数组

问题描述 投票:0回答:1

考虑这两个表

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_ORUDF..类似

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)))
sql google-bigquery
1个回答
0
投票

参见示例。 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

演示小提琴

© www.soinside.com 2019 - 2024. All rights reserved.