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;
我们正在将 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;