我想比较具有两个不同Oracle表的逗号分隔值的两列(差异表)的值。我想找到与所有值NAME1
都 匹配的行( 所有值都应与NAME2
值匹配)。
注意:逗号分隔值的顺序不同。
例子:
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
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
MY RESULT应该仅在两个表中显示基于“所有名称匹配”的匹配行。
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
尝试过REGEXP_SUBST
但无法使其正常工作。
我使用下面的代码来解析值:
SELECT REGEXP_SUBSTR (NAME1, '[^,]+', 1, ROWNUM)
FROM T1
CONNECT BY ROWNUM <= LENGTH (NAME1) -
LENGTH (REPLACE (NAME, ',')) + 1
您可以将表格转换为第一范式,然后比较存储在每一行中的化合物。起点可以是:
{1}对每行进行标记,然后将标记写入新表。给每个令牌其原始ID 加上
3个字母的前缀,以指示该令牌来自哪个表。{2}按ID对新(“规范化”)表的行进行分组,并执行LISTAGG()。执行自我连接,并找到匹配的“令牌组”。
{1}标记化,创建表为select(CTAS)
create table tokens
as
select
ltrim( -- ltrim() and rtrim() remove leading/trailing spaces (blanks)
rtrim(
substr( N.wrapped
, instr( N.wrapped, ',', 1, T.pos ) + 1
, ( instr( N.wrapped, ',', 1, T.pos + 1 ) - instr( N.wrapped, ',', 1, T.pos ) ) - 1
)
)
) token
, N.id
from (
select ',' || name1 || ',' as wrapped, 'T1_' || to_char( id_t1 ) as id from t1 -- names wrapped in commas, (table)_id
union all
select ',' || name2 || ',' , 'T2_' || to_char( id_t2 ) from t2
) N join (
select level as pos -- (max) possible position of char in an existing token
from dual
connect by level <= (
select greatest( -- find the longest string ie max position (query T1 and T2)
( select max( length( name1 ) ) from t1 )
, ( select max( length( name2 ) ) from t2 )
) as pos
from dual
)
) T
on T.pos <= ( length( N.wrapped ) - length( replace( N.wrapped, ',') ) ) - 1
;
不使用CONNECT BY进行标记化的灵感来自此SO答案。
不使用connect by
:
WITH CTE AS (SELECT 'a,b,c,d,e' temp,1 slno FROM DUAL
UNION
SELECT 'f,g',2 from dual
UNION
SELECT 'h',3 FROM DUAL
)
,x as (
select
','||temp||',' temp
,slno
from CTE
)
,iter as (SELECT rownum AS pos
FROM all_objects
)
select
SUBSTR(x.temp
,INSTR(x.temp, ',', 1, iter.pos) + 1
,INSTR(x.temp, ',', 1, iter.pos + 1)-INSTR(x.temp, ',', 1, iter.pos)-1
) temp
,x.slno
from x, iter
where iter.pos < = (LENGTH(x.temp) - LENGTH(REPLACE(x.temp, ','))) - 1;
TOKENS表的内容如下所示:
SQL> select * from tokens ;
TOKEN ID
ASCORBIC ACID T1_1
SODIUM HYDROGEN CARBONATE T1_2
CAFFEINE T1_3
PSEUDOEPHEDRINE HYDROCHLORIDE T1_4
PARACETAMOL T1_100
sodium hydroxide T1_110
POTASSIUM HYDROGEN CARBONATE T2_4
SODIUM HYDROGEN CARBONATE T2_5
PARACETAMOL PH. EUR. T2_6
CODEINE PHOSPHATE T2_7
DEXCHLORPHENIRAMINE MALEATE T2_8
DEXCHLORPHENIRAMINE MALEATE T2_10
PARACETAMOL T2_200
...
{2} GROUP BY,LISTAGG,自我加入
select
S1.id id1
, S2.id id2
, S1.tokengroup_T1
, S2.tokengroup_T2
from
(
select substr( id, 4, length( id ) - 3 ) id
, listagg( token, ' + ' ) within group ( order by token ) tokengroup_T1
from tokens
group by id
having substr( id, 1, 3 ) = 'T1_'
) S1
join
(
select substr( id, 4, length( id ) - 3 ) id
, listagg( token, ' + ' ) within group ( order by token ) tokengroup_T2
from tokens
group by id
having substr( id, 1, 3 ) = 'T2_'
) S2
on S1.tokengroup_T1 = S2.tokengroup_T2
;
-- result
ID1 ID2 TOKENGROUP_T1 TOKENGROUP_T2
4 10 DEXCHLORPHENIRAMINE MALEATE + PSEUDOEPHEDRINE HYDROCHLORIDE DEXCHLORPHENIRAMINE MALEATE + PSEUDOEPHEDRINE HYDROCHLORIDE
110 210 potassium carbonate + sodium hydroxide potassium carbonate + sodium hydroxide
1 4 ASCORBIC ACID + PARACETAMOL + POTASSIUM HYDROGEN CARBONATE ASCORBIC ACID + PARACETAMOL + POTASSIUM HYDROGEN CARBONATE
3 6 CAFFEINE + PARACETAMOL PH. EUR. CAFFEINE + PARACETAMOL PH. EUR.
以这种方式执行操作时,您可以使物质按字母顺序排列,并且还可以在此处选择所需的“定界符”(我们使用了“ +”)。
选择
如果这对您没有用,或者您认为这太复杂了,则可以尝试使用TRANSLATE()。在这种情况下,建议您从数据集中删除所有空格/空格(在查询中- 请勿
更改原始数据!),如下所示:
询问
select
id1, id2
, name1, name2
from (
select
id_t1 id1
, id_t2 id2
, T1.name1 name1
, T2.name2 name2
from T1
join T2
on translate( replace( T1.name1, ' ', '' ), replace( T2.name2, ' ', '' ), '!' )
= translate( replace( T2.name2, ' ', '' ), replace( T1.name1, ' ', '' ), '!' )
) ;
结果
ID1 ID2 NAME1 NAME2
2 5 SODIUM HYDROGEN CARBONATE, SODIUM CARBONATE ANHYDROUS, CITRIC ACID SODIUM HYDROGEN CARBONATE, SODIUM CARBONATE ANHYDROUS
3 6 CAFFEINE, PARACETAMOL PH. EUR. PARACETAMOL PH. EUR.,CAFFEINE
100 10 PARACETAMOL, DEXTROMETHORPHAN, PSEUDOEPHEDRINE, PYRILAMINE DEXCHLORPHENIRAMINE MALEATE, PSEUDOEPHEDRINE HYDROCHLORIDE
110 210 sodium hydroxide, potassium carbonate sodium hydroxide, potassium carbonate
注意: 我已将以下行添加到您的示例数据:
-- T1
110, 'sodium hydroxide, potassium carbonate'
-- T2
210, 'sodium hydroxide, potassium carbonate'
211, 'potassium hydroxide, sodium carbonate'
我发现很容易使用TRANSLATE()来给您“假阳性”,即ID为110、210和211的物质看起来会“匹配”。(换句话说:我认为这不是这项工作的正确工具。)
DBFIDDLE在这里
(点击链接以查看示例表和查询)。
问题内容: 假设我有两个表,表A和表B,并且我想比较某个列。 例如, 表A包含以下列:IP,主机,应用 表B具有以下列:IP,数据中心,服务器,模型,最后更新 如何比较两个表之间的IP列以获取差异? 我知道表是否具有相同的列,我可以使用并集和“减号”来获取差异,但是我无法找出表具有不同列的方式。 谢谢! 问题答案: 这将输出两个表中不匹配行的所有列,并且在任一侧都有NULL。
我有两个表,分别是产品和采购: PRODUCTS表-将获得购买的所有新产品。这意味着表prroducts中不存在相同的productname。所有独特产品列表 采购表-具有唯一purchase_id的所有采购产品的列表。 > 如果要在PURCHASE中添加或插入值,表PRODUCTS将获得PURCHASE的所有值,但前提是PURCHASE中的productname不存在于PRODUCTS中的'pr
问题内容: 比较mysql中逗号分隔的值,并在countcolumn中获取匹配的输出 例子: 通过比较ID 1和2,输出应为1 通过比较ID 2和3,输出应为1 通过比较ID 3和1,输出应为2 问题答案: 首先,您列出的数据实际上应该以一种格式存储,数据库的每一行都存储一个和一个,即3元素列表将对应3行。如果对您的结构进行了更改,则以下答案将是有意义的。 就目前而言,这是我整合的一个不错的MyS
问题内容: 我有2张桌子如下 笔记表 职位表 我想查询我的Notes表并将’forDepts’列与Positions表中的值相关联。 输出应为: 我知道数据库应该规范化,但是我不能更改此项目的数据库结构。 这将用于使用以下代码导出excel文件。 此代码仅输出“ forDepts”的第一个值 考试:执行人员(而不是执行人员,公司行政人员,Art) 可以通过CONCAT或FIND_IN_SET完成吗
我有一个关于列表比较器的问题。我有一个带有表格的网页应用程序。我可以在这个表格中编辑数据,也可以删除行。当我编辑数据时,标准比较器工作正常,但当我删除行时,我有问题。这个问题很常见(我想),当我删除一行时,javers比较旧列表和现在的列表时,看起来是这样的:旧列表有两个对象,现在列表有一个对象(我删除了第一个),现在javers不知道哪个对象被删除了,他比较旧列表中的第一个对象和新列表中的第二个
问题内容: 我有两个列表(不是Java列表,可以说两列) 例如 我想要一个返回多少个相同元素的方法。对于此示例,它应该为3,并且应该返回列表的相似值和不同的值。 如果是,我应该使用哈希图,然后用什么方法获得结果? 请帮忙 PS:这不是学校作业:)因此,如果您只是指导我就足够了 问题答案: 编辑 这是两个版本。一种使用,另一种使用 比较它们并从中创建您自己的版本,直到获得所需的内容。 这应该足以覆盖