Oracle使用带有SPLIT的WITH子句连接表[重复]
Posted
技术标签:
【中文标题】Oracle使用带有SPLIT的WITH子句连接表[重复]【英文标题】:Oracle joining tables using WITH clause with SPLIT [duplicate] 【发布时间】:2019-09-10 09:13:43 【问题描述】:我有这个表没有链接到另一个表,因为它们没有任何相同的列。现在他们想要一个链接两个表格的报告。
但问题是他们唯一的共同列是 WAFER_INFO 列,它有多个用逗号分隔的值,这就是为什么我需要拆分它们以创建多个记录但不同的 WAFER_INFO。
第一个表
select wafer_info
from bondertab_g3
where tha_reel_id='TGDT349028H'
order by insert_dm,tha_reel_id,processlk_ky
上述查询的结果
TGK343067-22,TGK343067-25,TGK343067-24,TGK343067-23
第二张桌子
select hp_part_nr,wafer_id,good_cnt,total_rej_cnt,processlk_ky,toollk_ky,toolnrlk_ky,materiallk_ky
from sawinsptab
where wafer_id ='TGK343067-22';
select hp_part_nr,wafer_id,good_cnt,total_rej_cnt,processlk_ky,toollk_ky,toolnrlk_ky,materiallk_ky
from sawinsptab
where wafer_id ='TGK343067-25';
select hp_part_nr,wafer_id,good_cnt,total_rej_cnt,processlk_ky,toollk_ky,toolnrlk_ky,materiallk_ky
from sawinsptab
where wafer_id ='TGK343067-24';
select hp_part_nr,wafer_id,good_cnt,total_rej_cnt,processlk_ky,toollk_ky,toolnrlk_ky,materiallk_ky
from sawinsptab
where wafer_id ='TGK343067-23';
基本上都在第一个表中
我已经了解如何使用此代码拆分所有这些记录
With DATA AS (
select tha_reel_id, wafer_info str
from bondertab_g3
where tha_reel_id='TGDT349028H'
)
SELECT A.tha_reel_id, trim(regexp_substr(A.str, '[^,]+', 1, LEVEL)) WAFERID FROM DATA A
CONNECT BY instr(str, ',', 1, LEVEL - 1) > 0
现在我的问题是,当唯一相同的列是 WAFERID 时,如何连接上面的查询并将其连接到第二个表
【问题讨论】:
如果您需要在加入之前拆分字符串,您有一个设计错误并且必须规范化您的数据。服务器不能在这些列上使用任何索引,并且必须扫描整个表以查找匹配项。即使是少量数据,这也会非常变慢 与示例 I/O 数据共享表结构,这将有所帮助 您的拆分函数将生成重复行,随着输入行数和分隔项数的增加,重复行的频率将呈指数增长(因为分层查询无法与特定父行相关,因此将与所有父行)。 【参考方案1】:查找sawinsptab.wafer_id
(包含在逗号分隔符中)是bondertab_g3.wafer_info
(包含在逗号分隔符中)的子字符串:
select hp_part_nr,
wafer_id,
good_cnt,
total_rej_cnt,
processlk_ky,
toollk_ky,
toolnrlk_ky,
materiallk_ky
from sawinsptab s
where EXISTS (
select 1
from bondertab_g3 b
where b.tha_reel_id='TGDT349028H'
and ','||b.wafer_info||',' LIKE '%,'||s.wafer_id||',%'
);
或
select s.hp_part_nr,
s.wafer_id,
s.good_cnt,
s.total_rej_cnt,
s.processlk_ky,
s.toollk_ky,
s.toolnrlk_ky,
s.materiallk_ky,
b.other_column
from sawinsptab s
INNER JOIN bondertab_g3 b
ON ( ','||b.wafer_info||',' LIKE '%,'||s.wafer_id||',%' )
where b.tha_reel_id='TGDT349028H';
或者,如果您需要在wafer_id
上使用索引并想要拆分分隔字符串,则可以使用递归子查询因式分解子句和简单的字符串函数(而不是慢速正则表达式):
select hp_part_nr,
wafer_id,
good_cnt,
total_rej_cnt,
processlk_ky,
toollk_ky,
toolnrlk_ky,
materiallk_ky
from sawinsptab s
where wafer_id IN (
WITH delimiter_bounds ( wafer_info, startidx, endidx ) AS (
SELECT wafer_info,
1,
INSTR( wafer_info, ',', 1 )
FROM bondertab_g3
WHERE tha_reel_id='TGDT349028H'
UNION ALL
SELECT wafer_info,
endidx + 1,
INSTR( wafer_info, ',', endidx + 1 )
FROM delimiter_bounds
WHERE endidx > 0
)
SELECT CASE
WHEN endidx = 0
THEN SUBSTR( wafer_info, startidx )
ELSE SUBSTR( wafer_info, startidx, endidx - startidx )
END
from delimiter_bounds
);
或
WITH delimiter_bounds ( wafer_info, other_column, startidx, endidx ) AS (
SELECT wafer_info,
other_column,
1,
INSTR( wafer_info, ',', 1 )
FROM bondertab_g3
WHERE tha_reel_id='TGDT349028H'
UNION ALL
SELECT wafer_info,
other_column,
endidx + 1,
INSTR( wafer_info, ',', endidx + 1 )
FROM delimiter_bounds
WHERE endidx > 0
)
select s.hp_part_nr,
s.wafer_id,
s.good_cnt,
s.total_rej_cnt,
s.processlk_ky,
s.toollk_ky,
s.toolnrlk_ky,
s.materiallk_ky,
b.other_column
from sawinsptab s
INNER JOIN (
SELECT CASE
WHEN endidx = 0
THEN SUBSTR( wafer_info, startidx )
ELSE SUBSTR( wafer_info, startidx, endidx - startidx )
END AS wafer_id,
other_column
FROM delimiter_bounds
) b
ON ( s.wafer_id = b.wafer_id )
【讨论】:
谢谢你,但如果我还需要选择中包含的第二个表bondertab_g3 上的数据怎么办?我试过添加它,但它没有出现。 @Gene 更新为INNER JOIN
【参考方案2】:
您可以将第一个查询更改为 CTE,然后直接在您的查询中使用它:
with data as (
select tha_reel_id, wafer_info str
from bondertab_g3
where tha_reel_id = 'TGDT349028H'
),
wafers as (
select d.tha_reel_id, trim(regexp_substr(d.str, '[^,]+', 1, LEVEL)) as waferid
from data d
connect by instr(str, ',', 1, LEVEL - 1) > 0
)
select s.*
from sawinsptab s
where wafer_id in (select w.waferid from wafers);
【讨论】:
以上是关于Oracle使用带有SPLIT的WITH子句连接表[重复]的主要内容,如果未能解决你的问题,请参考以下文章
WITH 子句可以在不使用 Select 语句的情况下具有硬编码值吗?