[英]NOT IN is not working as expected with Listagg function
下面是表的DDL
create or replace table tempdw.blk_table;
(
db_name varchar,
tbl_expr varchar
);
insert into tempdw.blk_table values ('edw','ABC%');
insert into tempdw.blk_table values ('edw','EFG%');
select * from tempdw.blk_table;
下面的代码不起作用,预计 output 不应返回任何
select * from tempdw.blk_table where tbl_expr not in (
select regexp_replace(regexp_replace(replace(listagg(tbl_expr,','),',','\',\''),'^','\''),'$','\'') from tempdw.blk_table);
当我在下面运行代码时它工作正常,试图理解为什么它不适用于上面的代码
select * from tempdw.blk_table where tbl_expr NOT IN('ABC%','EFG%');
Au contraire代码运行良好。 您不了解包含逗号的字符串和字符串列表之间的区别。
不幸的是,很难弄清楚你想要做什么,因为你的问题没有解释这一点。
我可以推测你想要类似的东西:
select bt.*
from blk_table bt
where db_name like tbl_expr;
然而,这只是一个猜测。
with data as (
select * from values ('edw','ABC%'),('edw','ABC%') v(db_name,tbl_expr )
)
select * from data
where tbl_expr not in (
select regexp_replace(regexp_replace(replace(listagg(tbl_expr,','),',','\',\''),'^','\''),'$','\'') from data);
确实给出了你不想要的结果。 又名:
DB_NAME TBL_EXPR
edw ABC%
edw ABC%
因为您的子查询只有一行结果,因为您已将两个输入聚合为一行。
REGEXP_REPLACE( REGEXP_REPLACE( REPLACE( LISTAGG( TBL_EXPR,','),',','\',\''),'^','\''),'$','\'')
'ABC%','ABC%'
而NOT IN
是完全匹配的。因此,如果我们从字符串更改为数字:
SELECT num, num in (2,3,4) FROM values (1),(3),(5) v(num);
给出:
NUM NUM IN (2,3,4)
1 0
3 1
5 0
所以你的NOT IN
只会返回不在你所拥有的列表中的字符串......并且给定你的列表是相同输入的聚合,根据定义,它们并不相同。
回到字符串..
SELECT str
,str in ('str_a', 'str_b')
,str not in ('str_a', 'str_b')
from values ('a'),('str_b') v(str);
给出:
STR STR IN ('STR_A', 'STR_B') STR NOT IN ('STR_A', 'STR_B')
a 0 1
str_b 1 0
因此你得到的结果..
现在我怀疑你想要 LIKE 类型行为或 REGEX 匹配,但鉴于你正在构建列表,你知道你在那里做什么..
另请注意:
listagg(tbl_expr,',') AS a
,replace(a,',','\',\'') AS b
,regexp_replace(b,'^','\'') AS c
,regexp_replace(c,'$','\'') AS d
是你正在做的效果可以替换为
listagg('\'' || tbl_expr || '\'',',')
除非您希望带有嵌入逗号的字符串成为独立的“列表”项..
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.