简体   繁体   English

Oracle 12c - 在插入选择中从 1 条记录中创建两条记录

[英]Oracle 12c - Creating two records out of 1 record in an insert select

I have a insert select query that brings back around 1 million records, each record has around 30 columns, there are two columns (performance total, mechanical total).我有一个插入选择查询,它带回大约 100 万条记录,每条记录大约有 30 列,有两列(性能总计,机械总计)。 One of these columns will have a value in them.其中一列将有一个值。 Performance Total could have nulll value, mechanical total could have null value or both could have values for that record. Performance Total 可能有 nulll 值,mechanical total 可能有 null 值,或者两者都有该记录的值。

When the record has a value in both columns (performance total, mechanical total) I want the SQL query to create two records, so two records are inserted into a table rather than one.当记录在两列(性能总计、机械总计)中都有值时,我希望 SQL 查询创建两条记录,因此将两条记录插入到一​​个表中而不是一个。 One record being the performance record and one a mechanical record.一项记录是性能记录,一项记录是机械记录。 The performance total or mechanical total will be inserted into a table where there's is total field.性能总计或机械总计将插入到有总计字段的表中。

How can this be done in an SQL query without creating a UNION statement as it cause performance issues??如何在不创建 UNION 语句的情况下在 SQL 查询中完成此操作,因为它会导致性能问题?

I don't suppose this is any more efficient that using a UNION, but you could do this:我不认为这比使用 UNION 更有效率,但你可以这样做:

insert into target (a, b, c, rec_type, rec_total)
select mt.a, mt.b, mt.c,
       case when r.rec = 1 then 'PERFORMANCE' else 'MECHANICAL' end 
       case when r.rec = 1 then mt.perf_total else mt.mech_total end 
from mytable mt
    cross join (select rownum rec from dual connect by level <= 2) r
where (mt.perf_total is not null and r.rec=1)
or (mt.mech_total is not null and r.rec = 2);

You are describing union all :您正在描述union all

select . . . , 'performance' as which, performance_total
from t
where performance_total is not null
union all
select . . . , 'mechanical' as which, mechanical_total
from t
where mechanical_total is not null;

This does require scanning the table twice.这确实需要扫描表两次。 I'm not sure if that is such a big hit on a base table with a million rows, which should fit into memory.我不确定这对具有一百万行的基表是否如此重要,它应该适合内存。

If it were (and this would be particularly true if the table were really a view), then I would phrase an unpivot as:如果是这样(如果表真的是一个视图,则尤其如此),那么我会将逆枢轴表述为:

select . . . , pm.which,
       (case when which = 'performance' then performance_total
             else mechanical_total
        end)
from t cross join
     (select 'performance' as which from dual union all
      select 'mechanical' as which from dual 
     ) pm
where (case when which = 'performance' then performance_total
            else mechanical_total
       end) is not null;

Or, in the most recent versions of Oracle, use a lateral join:或者,在最新版本的 Oracle 中,使用横向连接:

select . . . , pm.which, pm.total
from t cross join lateral
     (select 'performance' as which, performance_total as total from dual union all
      select 'mechanical' as which, mechanical_total from dual 
     ) pm
where total is not null;

Just to let you know I used the UNPIVOT on my records in the end it worked a treat.只是为了让您知道我在我的唱片中使用了 UNPIVOT,它最终奏效了。

SELECT TYPE_OF_RECORD, RECORD_POINTS, 28 columns 
FROM ( SELECT PERF_TOTAL, MECH_TOTAL, 28 columns 
       FROM TABLE   UNPIVOT (RECORD_POINTS FOR TYPE_OF_RECORD  IN
                             (PERF_TOTAL AS 'PERF',
                              MECH_TOTAL AS 'MECH'))  
       WHERE RECORD_POINTS > 0
 ) X;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM