我正在执行一些数据质量检查以识别不良数据,无法弄清楚如何执行检查-从而根据值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
答案 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
替代
另一种可能性是:以“人类可读”的形式创建一个包含所有有效映射的表,并使用它来验证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
答案 1 :(得分:0)
我强烈建议您创建一个表来表示T4
和T3
之间的一对多关系。这将是解决设计问题的第一步,同时提供一种解决当前问题的简单方法。
这是一个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