[英]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.