简体   繁体   English

根据另一个表中的规则从表中排除记录

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

Demo 演示

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.

相关问题 从一个表中获取记录,但不从另一个表中获取记录 - Get records from one table excluding records from another 如何选择表中的所有记录(不包括另一个记录) - How to select all records in a table excluding records from another 根据另一个表中的记录选择一个表中的记录 - Select records from one table based on records from another table 如何从数据库表中删除记录(不包括来自另一个SQL的记录) - How to delete records from database table excluding records from another SQL 根据另一个表中值的存在排除聚合函数中的记录 - Excluding records within an aggregate function based on presence of value in another table 根据另一个表的“相似”值从一个表中检索记录 - Retrieving records from one table based in 'similar' values of another table 如何根据来自另一个表的信息在表中插入新记录? - How to insert into a table new records based on info from another table? 根据另一个表中的条件在表中选择记录 - Selecting records in on table based on conditions from another table Select 基于条件的一个表中的所有记录,而不是另一个表中的所有记录 - Select all records from one table not in another table based on a condition 根据另一个表中的条件选择表中的记录? - Select records in on table based on conditions from another table?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM