[英]Excluding records from table based on rules from another table
I'm using Oracle SQL and I have a product table with diffrent attributes and sales volume for each product and another table with certain exclusion rules for different level of aggregation.我正在使用 Oracle SQL 并且我有一个产品表,每个产品具有不同的属性和销量,另一个表具有针对不同聚合级别的某些排除规则。 Let's look at the example:
让我们看一下这个例子:
Here is our main table with sales data on which we want to perform some calculations:这是我们的主表,其中包含我们要对其执行一些计算的销售数据:
And the other table contains diffrent rules which are supposed to exclude certain rows from table above:另一个表包含不同的规则,这些规则应该从上表中排除某些行:
When there is an "x", this column shouldn't be considered so our rules are: 1. exclude all rows with ATTR_3 = 'no' 2. exlcude all rows with ATTR_1 = 'Europe' and ATTR_2 = 'snacks' and ATTR_3 = 'no' 3. exlcude all rows with ATTR_1 = 'Africa'当有“x”时,不应考虑此列,因此我们的规则是: 1. 排除 ATTR_3 = 'no' 的所有行 2. 排除 ATTR_1 = 'Europe' 和 ATTR_2 = 'snacks' 和 ATTR_3 的所有行= 'no' 3. 排除 ATTR_1 = 'Africa' 的所有行
And based on that our final output should be like that:基于此,我们最终的 output 应该是这样的:
How this could be achived in SQL?如何在 SQL 中实现这一点? I was thinking about join but I have no idea how to handle different levels of aggregation for exclusions.
我正在考虑加入,但我不知道如何处理不同级别的排除聚合。
I think your expected output is wrong.我认为您预期的 output 是错误的。 None of the rules excludes the 2nd row (Europe - snacks - yes).
没有任何规则不包括第二排(欧洲 - 零食 - 是)。
SQL> with
2 -- sample data
3 test (product_id, attr_1, attr_2, attr_3) as
4 (select 81928 , 'Europe', 'beverages', 'yes' from dual union all
5 select 16534 , 'Europe', 'snacks' , 'yes' from dual union all
6 select 56468 , 'USA' , 'snacks' , 'no' from dual union all
7 select 129921, 'Africa', 'drinks' , 'yes' from dual union all
8 select 123021, 'Africa', 'snacks' , 'yes' from dual union all
9 select 165132, 'USA' , 'drinks' , 'yes' from dual
10 ),
11 rules (attr_1, attr_2, attr_3) as
12 (select 'x' , 'x' , 'no' from dual union all
13 select 'Europe', 'snacks', 'no' from dual union all
14 select 'Africa', 'x' , 'x' from dual
15 )
16 -- query you need
17 select t.*
18 from test t
19 where (t.attr_1, t.attr_2, t.attr_3) not in
20 (select
21 decode(r.attr_1, 'x', t.attr_1, r.attr_1),
22 decode(r.attr_2, 'x', t.attr_2, r.attr_2),
23 decode(r.attr_3, 'x', t.attr_3, r.attr_3)
24 from rules r
25 );
PRODUCT_ID ATTR_1 ATTR_2 ATT
---------- ------ --------- ---
81928 Europe beverages yes
16534 Europe snacks yes
165132 USA drinks yes
SQL>
You can use NOT EXISTS
您可以使用
NOT EXISTS
SELECT *
FROM sales s
WHERE NOT EXISTS (
SELECT 0
FROM attributes a
WHERE ( ( a.attr_1 = s.attr_1 AND a.attr_1 IS NOT NULL )
OR a.attr_1 IS NULL )
AND ( ( a.attr_2 = s.attr_2 AND a.attr_2 IS NOT NULL )
OR a.attr_2 IS NULL )
AND ( ( a.attr_3 = s.attr_3 AND a.attr_3 IS NOT NULL )
OR a.attr_3 IS NULL )
)
where I considered the x
values within the attributes
table as NULL
.我将
attributes
表中的x
值视为NULL
。 If you really have x
characters, then you can use :如果你真的有
x
字符,那么你可以使用:
SELECT *
FROM sales s
WHERE NOT EXISTS (
SELECT 0
FROM attributes a
WHERE ( ( NVL(a.attr_1,'x') = s.attr_1 AND NVL(a.attr_1,'x')!='x' )
OR NVL(a.attr_1,'x')='x' )
AND ( ( NVL(a.attr_2,'x') = s.attr_2 AND NVL(a.attr_2,'x')!='x' )
OR NVL(a.attr_2,'x')='x' )
AND ( ( NVL(a.attr_3,'x') = s.attr_3 AND NVL(a.attr_3,'x')!='x' )
OR NVL(a.attr_3,'x')='x' )
)
instead.反而。
You can use the join using CASE.. WHEN
statement as follows:您可以使用
CASE.. WHEN
语句进行连接,如下所示:
SELECT P.*
FROM PRODUCT P
JOIN RULESS R ON
(R.ATTR_1 ='X' OR P.ATTR_1 <> R.ATTR_1)
AND (R.ATTR_2 ='X' OR P.ATTR_2 <> R.ATTR_2)
AND (R.ATTR_3 ='X' OR P.ATTR_3 <> R.ATTR_3)
I would do this with three different not exists
:我会用三个不同的
not exists
来做到这一点:
select p.*
from product p
where not exists (select 1
from rules r
where r.attr_1 = p.attr_1 and r.attr_1 <> 'x'
) and
not exists (select 1
from rules r
where r.attr_2 = p.attr_2 and r.attr_2 <> 'x'
) and
not exists (select 1
from rules r
where r.attr_3 = p.attr_3 and r.attr_3 <> 'x'
) ;
In particular, this can take advantage of indexes on (attr_1)
, (attri_2)
and (attr_3)
-- something that is quite handy if you have a moderate number of rules.特别是,这可以利用
(attr_1)
、 (attri_2)
和(attr_3)
上的索引——如果您有适量的规则,这将非常方便。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.