根据白名单表过滤未过滤的表

Posted

技术标签:

【中文标题】根据白名单表过滤未过滤的表【英文标题】:Filter an unfiltered table against a whitelist table 【发布时间】:2017-11-26 11:27:03 【问题描述】:

简介

您好,我目前正在尝试构建一个基于 mysql 的过滤系统,但我现在遇到了如何解决的问题。我在下面的示例表链接中提供了两个表,一个包含白名单项目的白名单表和一个未排序表,它将根据白名单检查项目的列表。

PS:白名单不时变化

问题

如果只是匹配三列是否完全匹配,这将是一个非常容易的工作,但问题是,如果白名单中的列为NULL,那么这意味着它是一个通配符(如果有人可以提供更好的方法,可以更改此行为),这意味着该列中的任何值都被接受。必须通过所有三列才能接受条目。

这就是让我陷入困境的地方=\

示例

示例表:http://rextester.com/HMYT21528 或以下(相同)

-- unsorted data

create table unsorted (
    ID int AUTO_INCREMENT,
    country char(10) null,
    region  char(10) null,
    item    char(10),
    PRIMARY KEY (ID)
);

insert into unsorted(country, region, item) VALUES 

(null, null, "Apple"), (null, "East", "Apple"), (null, "West", "Apple"), 
("US", null, "Apple"), ("US", "East", "Apple"), ("US", "West", "Apple"), 
("CHINA", null, "Apple"), ("CHINA", "East", "Apple"), ("CHINA", "West", "Apple"),

(null, null, "Banana"), (null, "East", "Banana"), (null, "West", "Banana"), 
("US", null, "Banana"), ("US", "East", "Banana"), ("US", "West", "Banana"),
("CHINA", null, "Banana"), ("CHINA", "East", "Banana"), ("CHINA", "West", "Banana"),

(null, null, "Cat"), (null, "East", "Cat"), (null, "West", "Cat"), 
("US", null, "Cat"), ("US", "East", "Cat"), ("US", "West", "Cat"),
("CHINA", null, "Cat"), ("CHINA", "East", "Cat"), ("CHINA", "West", "Cat"),


(null, null, "Donkey"), (null, "East", "Donkey"), (null, "West", "Donkey"),
("US", null, "Donkey"), ("US", "East", "Donkey"), ("US", "West", "Donkey"), 
("CHINA", null, "Donkey"), ("CHINA", "East", "Donkey"), ("CHINA", "West", "Donkey");

-- white list data

create table whitelist (
    country char(10) null,
    region  char(10) null,
    item    char(10) not null
);

insert into whitelist(country, region, item) VALUES 

("US", "West", "Apple"), 
(null, "East", "Banana"), 
("CHINA", null, "Cat"), 
(null, null, "Donkey");

白名单中有这样一列:[ Country: Null, Region: East, Item: Banana ]

意思是对于未排序列表中的任何条目,只要是东部地区的香蕉,我们都会接受。

另一个例子是 [ Country: null, Region: null, Item: Donkey ]

这意味着我们将从任何国家或地区带走任何驴,因为为什么不呢?

预期输出

从上面的示例中,我预期的列表输出如下

[ 6, US, West Apple ]

[ 11, Null, East, Banana ]
[ 14, US, East, Banana ]
[ 17, China, East, Banana ]

[ 25, China, Null, Cat ]
[ 26, China, East, Cat ]
[ 27, China, West, Cat ]

[ 28, Null, Null, Donkey ]
[ 29, Null, East, Donkey ]
[ 30, Null, West, Donkey ]
[ 31, US, Null, Donkey ]
[ 32, US, East, Donkey ]
[ 33, US, West, Donkey ]
[ 34, China, Null, Donkey ]
[ 35, China, East, Donkey ]
[ 36, China, West, Donkey ]

编辑:回复 cmets

@Sloan Thrasher

SELECT a.*
FROM `unsorted` a
JOIN `whitelist` b
ON IF(b.`country` IS NULL,true,a.`country` = b.`country`) AND
    IF(b.`region` IS NULL,true,a.`region` = b.`region`) AND
    IF(b.`item` IS NULL,true,a.`item` = b.`item`);

由于白名单上没有“id”列,因此您的 where 子句会导致错误,而且选择应该选择未排序的结果,如果我要选择表 b,我只会看到过滤器,而不是我想看到的过滤数据。

【问题讨论】:

编辑您的问题并以表格格式将示例数据放入问题中 我没有那个选项,如果我要在这里转储示例数据,那会太长了。另外,我提供的链接是一个沙箱,您可以直接开始尝试,所以我看不出有什么理由把它放在这里会有帮助 =\ 【参考方案1】:

我认为这应该满足您的要求:

SELECT
    b.*
FROM `unsorted` a
JOIN `whitelist` b
ON IF(b.`country` IS NULL,true,a.`country` = b.`country`) AND
    IF(b.`region` IS NULL,true,a.`region` = b.`region`) AND
    IF(b.`item` IS NULL,true,a.`item` = b.`item`)
WHERE NOT b.`id` IS NULL;

【讨论】:

谢谢,但是,您的语法有很多错误,我必须先修复它,但这个解决方案一旦修复就可以正常工作,再次感谢 :) 修复语法错误后你得到了什么?您可以编辑您的问题并发布有效的最终查询吗?【参考方案2】:

我认为你可以用exists 子查询做你想做的事:

select u.*
from unsorted u
where exists (select 1
              from whitelist wl
              where (wl.country = u.country or wl.country is null) and
                    (wl.region = u.region or wl.region is null) and
                    (wl.item = u.item or wl.item is null)
             );

【讨论】:

它什么也不返回。 =\ @Willy_Sunny 。 . . “项目”不等于“国家”。 WHERE 子句中有错字。 啊,错过了,它也很有魅力,谢谢:D【参考方案3】:

这是另一种写法:

SELECT a.*
FROM unsorted a JOIN whitelist b
 ON a.country <=> COALESCE(b.country, a.country)
AND a.region  <=> COALESCE(b.region, a.region)
AND a.item    <=> COALESCE(b.item, a.item)

与@SloanThrasher 的答案类似的逻辑,但它使用了一些不同的逻辑运算符。

【讨论】:

以上是关于根据白名单表过滤未过滤的表的主要内容,如果未能解决你的问题,请参考以下文章

设置SSH登录IP白名单,过滤非法IP密码登录请求

什么是白名单和黑名单数据?

uniapp 监听通知栏消息插件(支持白名单黑名单过滤) Ba-NotifyListener

uniapp 监听通知栏消息插件(支持白名单黑名单过滤) Ba-NotifyListener

如何在 JWT 过滤器中将 api 列入白名单

AEM 中 doFilter servlet 的调度程序白名单