我会告诉你使用 PIVOT,这是一种非常简单的本地执行此类操作的方法,但不幸的是,我相信它是在 11g 中引入的。据我所知,您有两种选择;如果您想保留在原生 SQL 中,则必须使用硬编码的 case 语句。否则,此解决方案可能对您有用..
declare v_str varchar2(2000);
begin
v_str:='select factoryid,deptid,logdate';
for i in (select distinct 'H'||loghour||'_'||logmin a from test_table order by a) loop
v_str:=v_str||',max(case ''H''||loghour||''_''||logmin when '''||i.a||''' then counter end) as "'||i.a||'"';
end loop;
v_str:=v_str||' from test_table group by factoryid,deptid,logdate order by factoryid';
DBMS_OUTPUT.PUT_LINE(v_str);
end;
这将为您提供一个动态查询,然后您可以在循环或结果集中执行该查询,无论您选择什么(而不是我在这里的 PUT_LINE)。根据您提供的当前数据,此块的结果是:
select factoryid,deptid,logdate,
max(case 'H'||loghour||'_'||logmin when 'H0_0' then counter end) as "H0_0",
max(case 'H'||loghour||'_'||logmin when 'H0_30' then counter end) as "H0_30",
max(case 'H'||loghour||'_'||logmin when 'H1_0' then counter end) as "H1_0",
max(case 'H'||loghour||'_'||logmin when 'H1_30' then counter end) as "H1_30",
max(case 'H'||loghour||'_'||logmin when 'H2_0' then counter end) as "H2_0"
from test_table
group by factoryid,deptid,logdate order by factoryid
这将为您提供所需的准确信息。
编辑:请注意,包含 MAX 是为了消除 case 语句中的所有内容,使其不属于 group by。这是假设每个工厂 id/deptid/logdate 每次只有一个计数器值。
如果您想走本地路线并有一个定义的 loghour 和 logmin 列表(不是 100% 肯定,但看起来您会从 H0_0 到 H23_30),您可以使用查询 PL/ SQL 块在上面吐出,并继续创建 case 语句,直到所有 loghours 和 logmins 都被考虑在内。如果是这种情况并且 loghour/min 具有定义的跨度,则应该这样做,因为使用原生 SQL 优于动态 SQL 会带来性能优势,例如游标缓存。