union以指定的条件去重

with temp as(
select a,b,c from t1
union all
select a,b,c from t2
)
select a,b,c
from (select a,b,c,row_number() over (partition by a sort by b,c) rn from temp)
where rn=1
;
根据a列去重

业务场景:工单的去重

数据来源于mysql和es,一个工单在mysql中完成后,同步到es
如果mysql中该条数据没有删除,则会同步两次,在后面的old和new的full outer join中将会导致错误
因此需要在ods层处理该问题
采用窗口函数,按照orderid分区,按照来源排序,如果是重复的,取来源于es的数据

with temp as(

select

orderid ,
ordercreatetime ,
companyId ,
areasid ,
institutionid ,
platfromfiledcode ,
orderlargertype ,
ordersecondtype ,
orderthirdlytype ,
serviceflowalias ,
ordersource ,
ordersourcename ,
orderstatus ,
orderstatusname ,

actualhour ,
urgent ,
supervisenum ,
reworknum ,
importance,

dealuserids ,
dealuserorgids,
'es' as comefrom,
dt

from wfs_order_list_index where dt='$do_date'

union all 

select
id,
create_time,
company_id,
areas_id,
institution_id,
'' as platfromfiledcode,
order_larger_type,
order_second_type,
order_thirdly_type,
'' as serviceflowalias,
order_source,
'' as ordersourcename,
status,
'' as orderstatusname,
actual_hour,
urgent,
supervise_num,
rework_num,
importance,
deal_user_ids,
deal_user_org_ids,
'mysql' as comefrom,
dt

from tbwork_order where dt='$do_date'

)


insert overwrite table ods_order partition(dt)
select 

orderid ,
ordercreatetime ,
companyId ,
areasid ,
institutionid ,
platfromfiledcode ,
orderlargertype ,
ordersecondtype ,
orderthirdlytype ,
serviceflowalias ,
ordersource ,
ordersourcename ,
orderstatus ,
orderstatusname ,

actualhour ,
urgent ,
supervisenum ,
reworknum ,
importance,

dealuserids ,
dealuserorgids,
comefrom,
rn,
dt

 from (
select *,ROW_NUMBER() over(partition by orderid sort by comefrom) as rn from temp
)
where rn=1

https://wenwen.sogou.com/z/q705629911.htm

<think>嗯,用户问的是“oracle多表”,我需要先理解他们的具体需求。可能他们遇到了在多个表中存在复数据,想要合并或查询时复记录。首先,我得回忆一下Oracle中处理多表的常见方法。 首先想到的是使用UNION或者UNION ALL操作符。UNION会自动,而UNION ALL不会。但用户可能已经知道这点,或许他们需要更复杂的处理,比如多个表之间有部分复,或者需要根据某些条件。 然后,可能需要用ROWID或者分析函数,比如ROW_NUMBER()来标识复行。例如,对每个表中的数据按某个字段排序,然后取第一条,这样可以复。但如果是跨表,可能需要先合并所有表的数据,再进行全局。 另外,用户提到的多表可能指多个结构相同的表,或者是不同的表但有复数据。需要确认是否表结构一致,但假设用户是指结构相同的多个表,比如分表存储的情况,这时候用UNION ALL合并后再使用DISTINCT或GROUP BY。 还有一种情况是,用户可能需要使用EXISTS或IN子查询来排除其他表中的复记录。例如,从表A中排除那些在表B中已经存在的记录。 还要考虑性能问题,当处理大量数据时,UNION可能会比较慢,而UNION ALL加上后续的可能更高效。此外,临时表或者CTE(公用表表达式)也可能派上用场,把合并后的数据先存起来再处理。 可能还需要提醒用户注意数据一致性和事务处理,特别是在生产环境中操作时,可能需要备份数据或使用事务来回滚。 总结下来,可能的步骤包括:1. 使用UNION ALL合并多表;2. 应用方法如ROW_NUMBER()或GROUP BY;3. 处理后的结果插入临时表或直接查询。需要给出具体的示例,比如使用ROW_NUMBER()按某个字段分区排序,然后选择排名为1的记录。 另外,用户可能需要区分不同层次的:单表内、跨表,或者合并后整体。需要明确他们的情况,但作为通用方案,提供几种常见方法,并说明适用场景比较好。</think>在Oracle数据库中处理多表问题,通常需要结合SQL语句的集合操作、子查询或分析函数。以下是几种常见场景及解决方案: --- ### **一、多表合并后** 若多个表结构相同,需合并后除所有复记录: ```sql SELECT * FROM ( SELECT column1, column2 FROM table1 UNION ALL SELECT column1, column2 FROM table2 UNION ALL SELECT column1, column2 FROM table3 ) GROUP BY column1, column2 HAVING COUNT(*) >= 1; ``` 或直接使用`UNION`(自动): ```sql SELECT column1, column2 FROM table1 UNION SELECT column1, column2 FROM table2 UNION SELECT column1, column2 FROM table3; ``` --- ### **二、跨表关联** 若需要根据关联条件排除复记录,使用`EXISTS`或`NOT EXISTS`: ```sql -- 保留table1中在table2无复的记录 SELECT t1.* FROM table1 t1 WHERE NOT EXISTS ( SELECT 1 FROM table2 t2 WHERE t1.key_column = t2.key_column ); ``` --- ### **三、使用分析函数** 若需按优先级保留复记录(如保留最新数据): ```sql SELECT * FROM ( SELECT t.*, ROW_NUMBER() OVER ( PARTITION BY key_column ORDER BY create_time DESC ) AS rn FROM ( SELECT * FROM table1 UNION ALL SELECT * FROM table2 ) t ) WHERE rn = 1; ``` - `PARTITION BY`指定依据的列 - `ORDER BY`定义保留优先级 --- ### **四、临时表法处理大数据** 若数据量较大,可先将合并数据存入临时表再处理: ```sql CREATE GLOBAL TEMPORARY TABLE temp_table AS SELECT * FROM table1 UNION ALL SELECT * FROM table2; -- 对临时表 DELETE FROM temp_table WHERE rowid NOT IN ( SELECT MIN(rowid) FROM temp_table GROUP BY key_column ); ``` --- ### **关键要点** 1. **性能权衡**: - `UNION`自动但效率低 - `UNION ALL + GROUP BY`适合大数据量 2. **粒度**: - 根据业务需求选择字段 - 使用`ROW_NUMBER()`可实现灵活排序 3. **事务控制**: - 生产环境操作前建议备份数据 - 大表操作使用`COMMIT`分批提交 根据具体场景选择合适方法,建议先通过`EXPLAIN PLAN`分析执行计划优化性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值