如果a然后b签入where子句

时间:2019-02-23 01:23:54

标签: sql oracle

我正在执行一些数据质量检查以识别不良数据,无法弄清楚如何执行检查-从而根据值1与值2准确映射数据。

我最终需要确定T1中所有在T2中映射不正确的ID。我使用了以下代码,但似乎并没有得到期望的结果。映射不在数据库中,是需要输入数据的基础规则。
-当值包含在:Apples,Bananas,Cherries,Pears,Kiwis中时,则应将其映射为Fruit
-当输入值时:奶酪-然后是奶酪
-当价值在:腰果,杏仁-然后是坚果
-价值输入:吃喝玩乐-然后选择糖果
-当值:巧克力-然后为空

编辑:我已经添加了所需的输出。

SELECT t1.id, t2.*
FROM t1,t2,t3
WHERE 
    t1.id = t2.id
    AND (
        (t2.value1_id IN (01,04,05,08,09) AND t2.value2_id <> 2)
        OR (t2.value1_id = 02 and t2.value2_id <> 3)
        OR (t2.value1_id IN (03,10) and t2.value2_id <> 1)
        OR (t2.value1_id = 06 AND t2.value2_id <> 4)
        OR (t2.value1_id = 07 AND t2.value_id IS NOT NULL)
    )

T1

ID     
1    
2    
3 
4 
5   
6
7

T2

T1.ID Value1_ID Value2_ID    
1       01        2     
1       02        3     
1       03        1    
2       04        2    
2       05        2    
2       02        3    
2       06        4    
2       07             
3       08        2    
3       02        3    
4       09        2    
4       10        1    
5       02        2
5       10        1
6       04        3
6       10        2
7       07        2

T3

ID   Value1     
01   Apples    
02   Cheese    
03   Cashews    
04   Bananas    
05   Cherries    
06   Skittles    
07   Chocolate    
08   Pears    
09   Kiwis    
10   Almonds    

T4

ID  Value2    
1    Nuts    
2    Fruit    
3    Cheese    
4    Candy    

所需的输出:

T1.ID Value1_ID Value2_ID    
5       02            2
6       04            3    
6       10            2     
7       07            2   
  • T1.ID 5,value1_id 02在所需的输出中,因为奶酪映射到了水果
  • T1.ID 6,value1_id 04-香蕉映射到奶酪
  • T1.ID 6,value1_id 10-杏仁映射到水果
  • T1.ID 7,value1_id 07-巧克力应为空时映射到“水果”

3 个答案:

答案 0 :(得分:0)

问题之一是-在查看T2时-很难说出“映射”是否正确。 在为T1和T2创建测试数据时,我们对VALUE1_ID使用了CHAR,以便使后续查询更具“可读性”。

表格

create table T1( id primary key ) 
as
select 1 from dual union all
select 2 from dual union all
select 3 from dual ;


create table T2 ( id, value1_id, value2_id )
as
select 1, '01', 2 from dual union all
select 1, '02', 3 from dual union all
select 1, '03', 1 from dual union all
select 2, '04', 2 from dual union all
select 2, '05', 2 from dual union all
select 2, '02', 3 from dual union all
select 2, '06', 4 from dual union all
select 2, '07', null  from dual union all
select 3, '08', 2 from dual union all
select 3, '02', 3 from dual union all
select 4, '09', 2 from dual union all
select 4, '10', 1 from dual ;

重构查询

--
-- find incorrect mappings 
--
select t2.*, 'T1 id not valid' as status
from t2
where t2.id not in ( select id from T1 )
union all
select t2.*, 'value1_id <-> value2_id mapping incorrect '
from t1 join t2 on t1.id = t2.id
where
    ( t2.value1_id in ('01','04','05','08','09') and t2.value2_id <> 2 )
    or
    ( t2.value1_id = '02' and t2.value2_id <> 3 )
    or
    ( t2.value1_id in ('03','10') and t2.value2_id <> 1 )
    or
    ( t2.value1_id = '06' and t2.value2_id <> 4 )
    or
    ( t2.value1_id = '07' and t2.value2_id is null )
;

-- result
ID  VALUE1_ID  VALUE2_ID  STATUS                                      
4   10         1          T1 id not valid                             
4   09         2          T1 id not valid                             
2   07         NULL       value1_id <-> value2_id mapping incorrect 

DBfiddle

替代

另一种可能性是:以“人类可读”的形式创建一个包含所有有效映射的表,并使用它来验证T2中存储的映射。但是,只要您能获得正确的结果,请使用您更喜欢的任何方法。示例(经过Oracle 12c,18c测试)

-- in addition to tables T1, T2, T3, and T4: table with correct mappings
create table map( category, product )
as
select 'Fruit', 'Apples' from dual union all
select 'Cheese', 'Cheese' from dual union all
select 'Nuts', 'Cashews' from dual union all
select 'Fruit', 'Bananas' from dual union all
select 'Fruit', 'Cherries' from dual union all
select 'Candy', 'Skittles' from dual union all
select 'Candy', 'Chocolate' from dual union all
select 'Fruit', 'Pears' from dual union all
select 'Fruit', 'Kiwis' from dual union all
select 'Nuts', 'Almonds' from dual;

-- make sure that the entries in the MAP table tie in with T3 and T4
alter table map 
add (
  constraint m_pk primary key ( category, product )
, constraint m_category_fk foreign key ( category ) references T4 ( value2 )
, constraint m_product_fk foreign key ( product ) references T3 ( value1 )
) ;

查找不正确的映射

-- T2 rows containing incorrect (invalid) mappings
--   -> all rows MINUS the correct ones
select T2.id, T2.value1_id, T2.value2_id
from T2
minus (
  select T2.id, T2.value1_id, T2.value2_id
  from T2
    join (
  --
    select T4.id categoryid, T3.id productid, M.category, M.product
    from T4
      join map M on T4.value2 = M.category
      join T3    on T3.value1 = M.product
  --
  ) C -- correct mappings
    on 
      C.productid = T2.value1_id
  and C.categoryid = T2.value2_id
) ;

-- result
ID  VALUE1_ID  VALUE2_ID  
2   07         NULL 

DBfiddle

答案 1 :(得分:0)

我强烈建议您创建一个表来表示T4T3之间的一对多关系。这将是解决设计问题的第一步,同时提供一种解决当前问题的简单方法。

这是一个CREATE TABLE ... AS SELECT订单,使用您的示例数据初始化了这样的表:

create table cat AS
SELECT 1 t3_id, 2 t4_id FROM DUAL
UNION ALL SELECT 4, 2 FROM DUAL
UNION ALL SELECT 5, 2 FROM DUAL
UNION ALL SELECT 8, 2 FROM DUAL
UNION ALL SELECT 9, 2 FROM DUAL
UNION ALL SELECT 2, 3 FROM DUAL
UNION ALL SELECT 3, 1 FROM DUAL
UNION ALL SELECT 10, 1 FROM DUAL
UNION ALL SELECT 6, 4 FROM DUAL
UNION ALL SELECT 7, NULL FROM DUAL
;

有了此表,识别错误映射的记录就很简单:

SELECT t2.*
FROM t2
WHERE t2.Value2_ID IS NOT NULL AND NOT EXISTS (
    SELECT 1 FROM cat WHERE cat.t3_id = t2.Value1_ID AND cat.t4_id = t2.Value2_ID
)

DB Fiddle demo 和您的示例数据可得出:

T1_ID | VALUE1_ID | VALUE2_ID
----: | --------: | --------:
    5 |         2 |         2
    6 |         4 |         3
    6 |        10 |         2
    7 |         7 |         2

提示以进一步改进您的设计:T4(饮食系列)和T3(饮食系列)之间存在一对多的关系。代表这种情况的经典方法是在子表(T3)中添加引用父表的列。

答案 2 :(得分:0)

如果您无法使用水果到类别的映射来创建表,并且知道该值是静态的,则只需使用嵌套子查询或子查询分解子句将这些映射包括到查询中即可:

Oracle设置

create table T2 ( id, value1_id, value2_id ) as
select 1, '01', 2 from dual union all
select 1, '02', 3 from dual union all
select 1, '03', 1 from dual union all
select 2, '04', 2 from dual union all
select 2, '05', 2 from dual union all
select 2, '02', 3 from dual union all
select 2, '06', 4 from dual union all
select 2, '07', null  from dual union all
select 3, '08', 2 from dual union all
select 3, '02', 3 from dual union all
select 4, '09', 2 from dual union all
select 4, '10', 1 from dual union all
select 5, '02', 2 from dual union all
select 5, '10', 1 from dual union all
select 6, '04', 3 from dual union all
select 6, '10', 2 from dual union all
select 7, '07', 2 from dual;

查询

WITH mappings ( name, category ) AS (
  SELECT '01', 2 FROM DUAL UNION ALL
  SELECT '02', 3 FROM DUAL UNION ALL
  SELECT '03', 1 FROM DUAL UNION ALL
  SELECT '04', 2 FROM DUAL UNION ALL
  SELECT '05', 2 FROM DUAL UNION ALL
  SELECT '06', 4 FROM DUAL UNION ALL
  SELECT '07', NULL FROM DUAL UNION ALL
  SELECT '08', 2 FROM DUAL UNION ALL
  SELECT '09', 2 FROM DUAL UNION ALL
  SELECT '10', 1 FROM DUAL
)
SELECT *
FROM   T2 t
WHERE  NOT EXISTS (
  SELECT 1
  FROM   mappings m
  WHERE  t.value1_id = m.name
  AND    (  t.value2_id = m.category
         OR ( t.value2_id IS NULL AND m.category IS NULL ) )
);

结果

ID | VALUE1_ID | VALUE2_ID
-: | :-------- | --------:
 5 | 02        |         2
 6 | 04        |         3
 6 | 10        |         2
 7 | 07        |         2

db <>提琴here