DB2 到雪花迁移 - SQL:使用 'values' 子句得出结果 table

DB2 to Snowflake Migration - SQL: Deriving a result table using 'values' clause

我们正在将 DB2 迁移到 Snowflake,但在使用 'values' 子句时,我们 运行 遇到了范围不足的问题。 DB2 范围扩展到 select 查询中的所有表;而 Snowflake 仅限于子句中的那个:

在 DB2 中有效:

select * from
t_1
join

table (values
(t_1.c1, ‘foo’)
,(t_1.c1, ‘bar’)
) as t_2 (c1, c2)

on t_1.c5 = t_2.c2

在 Snowflake 中无效(语法略有不同 - 删除 'table'):

select * from
t_1
join

(values
(t_1.c1, ‘foo’)
,(t_1.c1, ‘bar’)
) as t_2 (c1, c2)

on t_1.c5 = t_2.c2

这会引发错误,提示“...t_1 未定义”。

有人知道 Snowflake 中的等效功能吗?

在某些情况下:此构造位于我们业务的良好嵌入式流程之后,对其进行返工将意味着重大投资。

它构成了传递到 ADF 管道的动态 ETL 查询的基础。有一个前端将组件部署到这个查询中——这个可部署的部分需要尽可能简单。它等同于“(t_1.c1, ‘foo’)”行,因此理想情况下,任何解决方案都会使这部分保持不变。

编辑:

对于一些额外的上下文...

在上面的例子中,我们有一个占位符来标识前端新部署的项目的插入点,如下所示:

select * from
t_1
join

table (values
(t_1.c1, ‘foo’)
,(t_1.c1, ‘bar’)
/*client_X_placeholder*/
) as t_2 (c1, c2)

on t_1.c5 = t_2.c2

union

select * from
t_1
join

table (values
(t_1.c1, ‘foo’)
,(t_1.c1, ‘bar’)
,(t_1.c2, 'barfoo')
/*client_Y_placeholder*/
) as t_2 (c1, c2)

on t_1.c5 = t_2.c2

我们正在提取一系列与客户端相关的指标,其中标签为 t_2.c2,结果为 t2.c1。相对于现实世界,这仍然是高度简化的。我们需要一种简单的方法来使用新指标及其计算来更新占位符 - t2.c1 可能包含在一堆函数中 and/or 驻留在 case 语句等中

嗯,该字符串几乎与 subquery/join 相关值:

我的第一个想法是:

WITH t_1 (c1, c5) as (
    SELECT 'a', 'bar'
)
select t_1.*, t_1.c1 as c1, t_2.c2 
from t_1
join values ('foo'),
  ('bar') as t_2(c2)
    on t_1.c5 = t_2.c2
;

但你想要的部分看起来像(如果可行的话):

WITH t_1 (c1, c5) as (
    SELECT 'a', 'bar'
)
select t_1.*, t_1.c1 as c1, t_2.c2 
from t_1
join values 
    (t_1.c1, 'foo'),
    (t_1.c1, 'bar')
        as t_2(c1,c2)
    on t_1.c5 = t_2.c2
;

但它不起作用....需要更多思考。

所以如果那个块是

(t_1.c1, 'foo'),
(t_1.c1, 'bar')

然后你可以用%%stuff%%

把它捣碎成块

然后撕开它然后跳圈..

WITH t_1 (c1, c5) as (
    SELECT 'a', 'bar'
), magic as (         
    SELECT 
       split(t.value, ',') as p
       ,trim(get(p,0),'"') as p0
       ,trim(get(p,1),' \'")') as p1
    
    FROM table(split_to_table($$(t_1.c1, 'foo'),
                              (t_1.c1, 'bar')$$,'(')) as t
    WHERE t.value <> ''
), hoop_jumping(c1, c2) as (
    SELECT 
        case p0
               WHEN 't_1.c1' then t_1.c1
               WHEN 't_1.c5' then t_1.c5
        end,
        p1
    FROM magic, t_1
)
SELECT t.*, h.*
FROM t_1 as t
JOIN hoop_jumping as h
   ON t.c5 = h.c2

只要您愿意涵盖所选内容的所有基础:

C1 C5 C1 C2
a bar a bar

但我怀疑将该块注入雪花脚本块并将其用作注入代码更有意义。

我不知道这在 snowflake 中是否有效,但是 SQL 如果您想在其中引用 t_1 ,则需要您将 t_2 声明为 LATERAL。 Db2 使用 tables 作为横向的同义词(同样有效)。所以你可以试试:

select * 
from t_1
join LATERAL (
    values (t_1.c1, ‘foo’)
         , (t_1.c1, ‘bar’)
    ) as t_2 (c1, c2)
  on t_1.c5 = t_2.c2

Lateral 在 SQL99 年引入,并得到包括 Db2 在内的许多 DBMS 的支持。

在 Db2 中,TABLE 通常在从返回 table 的函数中进行选择时使用:

SELECT * FROM TABLE ( myfun() )

有点相似所以我想这就是为什么 TABLE 可以作为 LATERAL 的同义词(只是猜测)。

我做了一些谷歌搜索,雪花文档中描述了 LATERAL:join-lateral

编辑:

显然,在派生 table 中加入值子句时存在限制。 Simeon Pilgrim 的回答包含对此

的修复

Lennart 值得拥有这个,他的代码非常接近

WITH t_1 (c1, c5) as (
    SELECT 'a', 'bar'
)
select *
from t_1
join lateral (values 
    (t_1.c1, 'foo'),
    (t_1.c1, 'bar')
    )  as t_2(c1,c2)
    on t_1.c5 = t_2.c2;

但这会导致内部错误:

000603 (XX000): SQL execution internal error: Processing aborted due to error 300002:4143448929; incident 4919401.

但是如果你把 SELECT * FROM 放在那里:

WITH t_1 (c1, c5) as (
    SELECT 'a', 'bar'
)
select *
from t_1
join lateral (select * from values 
    (t_1.c1, 'foo'),
    (t_1.c1, 'bar')
    ) as t_2(c1,c2)  
    on t_1.c5 = t_2.c2;

有效:

C1 C5 C1 C2
a bar a bar

Lenart 的 try more brackets 也适用:

WITH t_1 (c1, c5) as (
    SELECT 'a', 'bar'
)
select *
from t_1
join lateral (
    select * from (
        values 
        (t_1.c1, 'foo'),
        (t_1.c1, 'bar')
    )
) as t_2(c1,c2)  
    on t_1.c5 = t_2.c2;