我想比较两列(差异表)的值,这些列具有两个不同的Oracle表的逗号分隔值。我想找到与所有值都匹配的行(NAME1所有值都应与NAME2值匹配)。
注意:逗号分隔值的顺序不同。
示例:
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
“我的结果”应仅在两个表中显示基于“所有名称匹配”的匹配行。
T1:
ID_T1 NAME1
===================================
1 ASCORBIC ACID, PARACETAMOL, POTASSIUM HYDROGEN CARBONATE
2 SODIUM HYDROGEN CARBONATE, SODIUM CARBONATE ANHYDROUS, CITRIC ACID
3 CAFFEINE, PARACETAMOL PH. EUR.
4 PSEUDOEPHEDRINE HYDROCHLORIDE,DEXCHLORPHENIRAMINE MALEATE
5 PARACETAMOL, DEXTROMETHORPHAN, PSEUDOEPHEDRINE, PYRILAMINE
T2:
ID_T2 NAME2
=================================
4 POTASSIUM HYDROGEN CARBONATE, ASCORBIC ACID, PARACETAMOL
5 SODIUM HYDROGEN CARBONATE, SODIUM CARBONATE ANHYDROUS
6 PARACETAMOL PH. EUR.,CAFFEINE
7 CODEINE PHOSPHATE, PARACETAMOL DC
8 DEXCHLORPHENIRAMINE MALEATE, DEXTROMETHORPHAN HYDROBROMIDE
10 DEXCHLORPHENIRAMINE MALEATE, PSEUDOEPHEDRINE HYDROCHLORIDE
11 PARACETAMOL, DEXTROMETHORPHAN, PSEUDOEPHEDRINE, PYRILAMINE1
下面的现有成员@Goran提供了PARTIAL解决方案,下面的解决方案适用于除最后一行以外的所有值。下面的解决方案是找到T1的第5行与T2的第11行的匹配这是错误的,因为T2的最后一行是“ PYRILAMINE1”,这是<>到T1最后一行是“ PYRILAMINE” < / p>
ID_T1 ID_T2 MATCHING NAME
==================================
1 4 POTASSIUM HYDROGEN CARBONATE, ASCORBIC ACID, PARACETAMOL
3 6 PARACETAMOL PH. EUR.,CAFFEINE
4 10 PSEUDOEPHEDRINE HYDROCHLORIDE,DEXCHLORPHENIRAMINE MALEATE
答案 0 :(得分:0)
这是一种方法,纯粹是用SQL而不利用Oracle 12及更高版本的任何功能(因为您没有告诉我们您的版本,所以我不想做假设)。如果发现自己多次需要这种比较,那么最好按照下面的代码所示编写“ normalize_string”函数,并在需要时使用它。它的作用(以及下面的代码的作用)是将逗号分隔的字符串拆分为标记,在每个标记的开头和结尾处修剪空格,将每个标记转换为大写(允许使用小写字母输入)字母),去重复的标记(允许同一标记在输入中出现多次),然后重新创建以逗号分隔的列表,并且标记以字母顺序出现。这样就可以将结果字符串彼此进行比较。
更好的是,如果它在您的权限之内(可以自己执行或影响老板执行此操作),则可以更改数据模型。您应该为单独的成分准备一个单独的小表格,并带有一个主键(也许是一个数字,肯定不是成分名称),以供其他表格参考。然后,您需要一个单独的药品小表,也要有一个主键(而不是药品名称!),最后是一个多对多关系表,每种药物中的每种成分都有一行-两者均由各自的键标识(不按名称)。这将避免药物或成分名称中的错别字,小写而不是大写等,这将使您的所有代码更容易编写,测试和维护,并且速度更快。你能做到吗?
= = = = = = =
在下面的输出中,我显示在t1
中出现的“名称”(在您想要的输出中,您显示在t2
中出现的名称,但我认为您不在乎)。也许最好显示规范化的版本(用norm1
代替name1
)。
select n1.id_t1, n2.id_t2, n1.name1
from
( select id_t1, name1, listagg(token, ', ') within group (order by token) norm1
from ( select distinct id_t1, name1,
upper(trim(substr(str, instr(str, ',', 1, level) + 1,
instr(str, ',', 1, level + 1)
- instr(str, ',', 1, level) - 1))) token
from (select id_t1, name1, ',' || name1 || ',' as str from t1)
connect by level <= length(str) - length(replace(str, ',')) - 1
and prior id_t1 = id_t1
and prior sys_guid() is not null
)
group by id_t1, name1
) n1
inner join
( select id_t2, name2, listagg(token, ', ') within group (order by token) norm2
from ( select distinct id_t2, name2,
upper(trim(substr(str, instr(str, ',', 1, level) + 1,
instr(str, ',', 1, level + 1)
- instr(str, ',', 1, level) - 1))) token
from (select id_t2, name2, ',' || name2 || ',' as str from t2)
connect by level <= length(str) - length(replace(str, ',')) - 1
and prior id_t2 = id_t2
and prior sys_guid() is not null
)
group by id_t2, name2
) n2
on n1.norm1 = n2. norm2
;
输出
ID_T1 ID_T2 NAME1
------ ------ ------------------------------------------------------------------
1 4 ASCORBIC ACID, PARACETAMOL, POTASSIUM HYDROGEN CARBONATE
3 6 CAFFEINE, PARACETAMOL PH. EUR.
4 10 PSEUDOEPHEDRINE HYDROCHLORIDE,DEXCHLORPHENIRAMINE MALEATE