简体   繁体   English

NOT IN 无法与 Listagg function 一起按预期工作

[英]NOT IN is not working as expected with Listagg function

Below is the DDL of the table下面是表的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;

在此处输入图像描述

Below code is not working, expected output should not return any下面的代码不起作用,预计 output 不应返回任何

select * from tempdw.blk_table where tbl_expr not in (
       select regexp_replace(regexp_replace(replace(listagg(tbl_expr,','),',','\',\''),'^','\''),'$','\'') from tempdw.blk_table);

When I run below code it works fine, Trying to understand why it's not working for above code当我在下面运行代码时它工作正常,试图理解为什么它不适用于上面的代码

select * from tempdw.blk_table where tbl_expr NOT IN('ABC%','EFG%');

Au contraire The code is working just fine. Au contraire代码运行良好。 You don't understand the difference between a string that has commas and a list of strings.您不了解包含逗号的字符串和字符串列表之间的区别。

Unfortunately, it is rather hard to figure out what you do want to do, because your question does not explain that.不幸的是,很难弄清楚想要做什么,因为你的问题没有解释这一点。

I can speculate that you want something like:我可以推测你想要类似的东西:

select bt.*
from blk_table bt
where db_name like tbl_expr;

This is just a guess, however.然而,这只是一个猜测。

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);

does indeed give the results you don't want.确实给出了你不想要的结果。 aka:又名:

DB_NAME TBL_EXPR
edw ABC%
edw ABC%

because your sub-query only has one row of results, because you have aggregated the two input into one row.因为您的子查询只有一行结果,因为您已将两个输入聚合为一行。

REGEXP_REPLACE( REGEXP_REPLACE( REPLACE( LISTAGG( TBL_EXPR,','),',','\',\''),'^','\''),'$','\'')
 'ABC%','ABC%'

and NOT IN is a exact match.. thus if we change from strings to numbers:NOT IN是完全匹配的。因此,如果我们从字符串更改为数字:

SELECT num, num in (2,3,4) FROM values (1),(3),(5) v(num);  

gives:给出:

 NUM    NUM IN (2,3,4)
 1      0
 3      1
 5      0

so your NOT IN would only return strings that are not in the list of one you have... and given your list is the aggregate of the same input, that are by definition not that same.所以你的NOT IN只会返回不在你所拥有的列表中的字符串......并且给定你的列表是相同输入的聚合,根据定义,它们并不相同。

back to strings..回到字符串..

SELECT str
    ,str in ('str_a', 'str_b')
    ,str not in ('str_a', 'str_b')
from values ('a'),('str_b') v(str);

gives:给出:

STR    STR IN ('STR_A', 'STR_B')    STR NOT IN ('STR_A', 'STR_B')
a       0                           1
str_b   1                           0

Thus the results you are getting..因此你得到的结果..

now I suspect you are want LIKE type behavior OR a REGEX match, but given you are building the list you know what you are doing there..现在我怀疑你想要 LIKE 类型行为或 REGEX 匹配,但鉴于你正在构建列表,你知道你在那里做什么..

also note:另请注意:

listagg(tbl_expr,',') AS a
    ,replace(a,',','\',\'') AS b
    ,regexp_replace(b,'^','\'') AS c
    ,regexp_replace(c,'$','\'') AS d

is the effect of what you are doing can be replaced with是你正在做的效果可以替换为

listagg('\'' || tbl_expr || '\'',',')

unless you want strings with embedded comma to become independent "list" items..除非您希望带有嵌入逗号的字符串成为独立的“列表”项..

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM